ui: Support for SSO with Admin Partitions (#11604)

* Upgrade AuthForm and document current state a little better
* Hoist SSO out of the AuthForm
* Bare minimum admin partitioned SSO

also:

ui: Tabbed Login with Token or SSO interface (#11619)

- I upgraded our super old, almost the first ember component I wrote, to use glimmer/almost template only. This should use slots/contextual components somehow, but thats a bigger upgrade so I didn't go that far.
- I've been wanting to upgrade the shape of our StateChart component for a very long while now, here its very apparent that it would be much better to do this sooner rather than later. I left it as is for now, but there will be a PR coming soon with a slight reshaping of this component.
- Added a did-upsert modifier which is a mix of did-insert/did-update
- Documentation added/amended for all the new things.
This commit is contained in:
John Cowen 2021-11-24 14:53:12 +00:00 committed by GitHub
parent b1c4be3da0
commit 3d1b859533
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1153 additions and 369 deletions

3
.changelog/11604.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
ui: Add partition support for SSO
```

View File

@ -18,4 +18,8 @@ export default class AuthMethodAbility extends BaseAbility {
get canDelete() {
return this.env.var('CONSUL_ACLS_ENABLED') && super.canDelete;
}
get canUse() {
return this.env.var('CONSUL_SSO_ENABLED');
}
}

View File

@ -4,7 +4,12 @@ class: ember
# AuthDialog
```hbs preview-template
<AuthDialog @dc={{'dc-1'}} @nspace={{'default'}} @onchange={{action (noop)}} as |api components|>
<AuthDialog
@dc={{'dc-1'}}
@nspace={{'default'}}
@partition={{'default'}}
@onchange={{action (noop)}}
as |api components|>
{{#let components.AuthForm components.AuthProfile as |AuthForm AuthProfile|}}
<BlockSlot @name="unauthorized">
Here's the login form:
@ -27,6 +32,7 @@ A component to help orchestrate a login/logout flow.
| --- | --- | --- | --- |
| `dc` | `String` | | The name of the current datacenter |
| `nspace` | `String` | | The name of the current namespace |
| `partition` | `String` | | The name of the current partition |
| `onchange` | `Function` | | An action to fire when the users token has changed (logged in/logged out/token changed) |
### Methods/Actions/api

View File

@ -1,8 +1,20 @@
<StateChart @src={{chart}} as |State Guard Action dispatch state|>
<StateChart
@src={{chart}}
as |State Guard Action dispatch state|>
<Guard
@name="hasToken"
@cond={{action 'hasToken'}}
/>
<Action
@name="login"
@exec={{action 'login'}}
/>
<Action
@name="logout"
@exec={{action 'logout'}}
/>
<Guard @name="hasToken" @cond={{action 'hasToken'}} />
<Action @name="login" @exec={{action 'login'}} />
<Action @name="logout" @exec={{action 'logout'}} />
{{! This DataSource just permanently listens to any changes to the users }}
{{! token, whether thats a new token, a changed token or a deleted token }}
<DataSource

View File

@ -1,19 +1,47 @@
---
class: ember
---
# AuthForm
AuthForm is a mostly template only form component specifically for user
authentication for the UI. The component uses `TokenSource` which performs the
necessary functionality all composed together using a StateChart to
orchestrate the flow.
Errors are contained/rendered within the form itself.
```hbs preview-template
<AuthForm as |api|></AuthForm>
<AuthForm
@dc={{'dc-1'}}
@partition={{'default'}}
@nspace={{'default'}}
@onsubmit={{noop}}
as |api|></AuthForm>
```
### Methods/Actions/api
## Arguments
| Method/Action | Description |
| Argument | Type | Default | Description |
| --- | --- | --- | --- |
| `dc` | `String` | | The name of the current datacenter |
| `nspace` | `String` | | The name of the current namespace |
| `partition` | `String` | | The name of the current partition |
| `onsubmit` | `Function` | | The action to fire when the form is submitted |
## Exported API
| Name | Type | Description |
| --- | --- | --- |
| `submit` | `Function` | Submit the form with a `{Name: 'oidc', Value: 'provider-name'}` which will eventually be passed as the `value` to the TokenSource |
| `focus` | `Function` | Focus the input field |
| `error` | `Function` | Fire an error to be displayed in the form |
| `reset` | `Function` | Reset the form back to its original empty/non-error state |
| `disabled` | `Boolean` | Whether the form is currently disabled or not |
## Slots
| Name | Description |
| --- | --- |
| `reset` | Reset the form back to its original empty/non-error state |
| `content` | Provides a configurable slot underneath the form for addition of other login widgets, in our case SSO |
### See
## See
- [Component Source Code](./index.js)
- [Template Source Code](./index.hbs)

View File

@ -7,6 +7,11 @@ export default {
target: 'idle',
},
],
ERROR: [
{
target: 'error',
},
],
},
states: {
idle: {
@ -23,15 +28,7 @@ export default {
],
},
},
loading: {
on: {
ERROR: [
{
target: 'error',
},
],
},
},
loading: {},
error: {
exit: ['clearError'],
on: {

View File

@ -1,41 +1,93 @@
<StateChart @src={{chart}} as |State Guard Action dispatch state|>
{{yield (hash
<StateChart
@src={{this.chart}}
as |State Guard ChartAction dispatch state|>
{{#let
(hash
State=State
Guard=Guard
Action=ChartAction
dispatch=dispatch
state=state
)
as |chart|}}
{{#let
(hash
reset=(action dispatch "RESET")
focus=(action 'focus')
)}}
<Guard @name="hasValue" @cond={{action 'hasValue'}} />
focus=this.focus
disabled=(state-matches state "loading")
error=(queue
(action dispatch "ERROR")
(action (mut this.error) value="error.errors.firstObject")
)
submit=(queue
(action (mut this.value))
(action dispatch "SUBMIT")
)
)
as |exported|}}
<Guard
@name="hasValue"
@cond={{this.hasValue}}
/>
{{!TODO: Call this reset or similar }}
<Action @name="clearError" @exec={{queue (action (mut error) undefined) (action (mut secret) undefined)}} />
<div class="auth-form" ...attributes>
<chart.Action
@name="clearError"
@exec={{queue (action (mut this.error) undefined) (action (mut this.secret) undefined)}}
/>
<div
class="auth-form"
...attributes
>
<StateChart
@src={{this.tabsChart}}
as |TabState IgnoredGuard IgnoredAction tabDispatch tabState|>
{{#if (can 'use SSO')}}
<TabNav
@items={{array
(hash
label='Token'
selected=(state-matches tabState 'token')
)
(hash
label='SSO'
selected=(state-matches tabState 'sso')
)
}}
@onclick={{queue (action tabDispatch) (action dispatch "RESET")}}
/>
{{/if}}
<State @matches="error">
{{#if error.status}}
{{#if this.error.status}}
<Notice
@type="error"
role="alert"
as |notice|>
<notice.Body>
<p>
{{#if value.Name}}
{{#if (eq error.status '403')}}
{{#if this.value.Name}}
{{#if (eq this.error.status '403')}}
<strong>Consul login failed</strong><br />
We received a token from your OIDC provider but could not log in to Consul with it.
{{else if (eq error.status '401')}}
{{else if (eq this.error.status '401')}}
<strong>Could not log in to provider</strong><br />
The OIDC provider has rejected this access token. Please have an administrator check your auth method configuration.
{{else if (eq error.status '499')}}
{{else if (eq this.error.status '499')}}
<strong>SSO log in window closed</strong><br />
The OIDC provider window was closed. Please try again.
{{else}}
<strong>Error</strong><br />
{{error.detail}}
{{this.error.detail}}
{{/if}}
{{else}}
{{#if (eq error.status '403')}}
{{#if (eq this.error.status '403')}}
<strong>Invalid token</strong><br />
The token entered does not exist. Please enter a valid token to log in.
{{else if (eq this.error.status '404')}}
<strong>No providers</strong><br />
No SSO providers are configured for that Admin Partition.
{{else}}
<strong>Error</strong><br />
{{error.detail}}
{{this.error.detail}}
{{/if}}
{{/if}}
</p>
@ -43,25 +95,34 @@
</Notice>
{{/if}}
</State>
<form onsubmit={{action dispatch "SUBMIT"}}>
<TabState @matches="token">
<form
onsubmit={{action dispatch "SUBMIT"}}
>
<fieldset>
<label class={{concat "type-password" (if (and (state-matches state 'error') (not error.status)) ' has-error' '')}}>
<label
class={{concat "type-password" (if (and (state-matches state 'error') (not this.error.status)) ' has-error')}}
>
<span>Log in with a token</span>
{{! Blink/Webkit based seem to leak password inputs }}
{{! this will only occur during acceptance testing so }}
{{! turn them into text inputs during acceptance testing }}
<input
{{ref this 'input'}}
{{did-insert (set this 'input')}}
disabled={{state-matches state "loading"}}
type={{inputType}}
type={{if (eq (env 'environment') 'testing') 'text' 'password'}}
name="auth[SecretID]"
placeholder="SecretID"
value={{secret}}
value={{this.secret}}
oninput={{queue
(action (mut secret) value="target.value")
(action (mut value) value="target.value")
(action (mut this.secret) value="target.value")
(action (mut this.value) value="target.value")
(action dispatch "TYPING")
}}
/>
<State @matches="error">
{{#if (not error.status)}}
{{#if (not this.error.status)}}
<strong role="alert">
Please enter your secret
</strong>
@ -69,47 +130,35 @@
</State>
</label>
</fieldset>
<button type="submit" disabled={{state-matches state "loading"}}>
<Action
@type="submit"
disabled={{state-matches state "loading"}}
>
Log in
</button>
<em>Contact your administrator for login credentials.</em>
</Action>
</form>
{{#if (env 'CONSUL_SSO_ENABLED')}}
{{!-- This `or` can be completely removed post 1.10 as 1.10 has optional params with default values --}}
<DataSource
@src={{uri '/${partition}/${nspace}/${dc}/oidc/providers'
(hash
partition=partition
nspace=nspace
dc=dc
)
}}
@onchange={{queue (action (mut providers) value="data")}}
@onerror={{queue (action (mut error) value="error.errors.firstObject")}}
@loading="lazy"
/>
{{#if (gt providers.length 0)}}
<p>
<span>or</span>
</p>
{{/if}}
<OidcSelect
@items={{providers}}
@disabled={{state-matches state "loading"}}
@onchange={{queue (action (mut value)) (action dispatch "SUBMIT") }}
@onerror={{queue (action (mut error) value="error.errors.firstObject") (action dispatch "ERROR")}}
/>
{{/if}}
</TabState>
{{yield (assign exported (hash Method=TabState))}}
<em>
Contact your administrator for login credentials.
</em>
</StateChart>
</div>
<State @matches="loading">
<TokenSource
@dc={{dc}}
@nspace={{or value.Namespace nspace}}
@partition={{or value.Partition partition}}
@type={{if value.Name 'oidc' 'secret'}}
@value={{if value.Name value.Name value}}
@onchange={{queue (action dispatch "RESET") (action onsubmit)}}
@onerror={{queue (action (mut error) value="error.errors.firstObject") (action dispatch "ERROR")}}
@dc={{@dc}}
@nspace={{or this.value.Namespace @nspace}}
@partition={{or this.value.Partition @partition}}
@type={{if this.value.Name 'oidc' 'secret'}}
@value={{if this.value.Name this.value.Name this.value}}
@onchange={{queue (action dispatch "RESET") @onsubmit}}
@onerror={{queue (action (mut this.error) value="error.errors.firstObject") (action dispatch "ERROR")}}
/>
</State>
{{/let}}
{{/let}}
</StateChart>

View File

@ -1,29 +1,23 @@
import Component from '@ember/component';
import { computed } from '@ember/object';
import Ember from 'ember';
import Component from '@glimmer/component';
import { action } from '@ember/object';
import chart from './chart.xstate';
import tabs from './tabs.xstate';
export default Component.extend({
tagName: '',
onsubmit: function(e) {},
onchange: function(e) {},
// Blink/Webkit based seem to leak password inputs
// this will only occur during acceptance testing so
// turn them into text inputs during acceptance testing
inputType: computed(function() {
return Ember.testing ? 'text' : 'password';
}),
init: function() {
this._super(...arguments);
export default class AuthForm extends Component {
constructor() {
super(...arguments);
this.chart = chart;
},
actions: {
hasValue: function(context, event, meta) {
return this.value !== '' && typeof this.value !== 'undefined';
},
focus: function() {
this.input.focus();
},
},
});
this.tabsChart = tabs;
}
@action
hasValue(context, event, meta) {
return this.value !== '' && typeof this.value !== 'undefined';
}
@action
focus() {
this.input.focus();
}
}

View File

@ -1,34 +1,23 @@
%auth-form {
width: 320px;
margin: 10px 25px;
margin: 0 25px;
margin-top: -20px;
}
%auth-form em {
display: inline-block;
margin-top: 1em;
}
%auth-form form,
%auth-form .oidc-select {
padding-top: 1em;
}
%auth-form form {
margin-bottom: 0.5em !important;
margin-bottom: 0 !important;
}
%auth-form .ember-basic-dropdown-trigger,
%auth-form button {
%auth-form button:not(.reset) {
width: 100%;
}
%auth-form .progress {
margin: 0 auto;
}
%auth-form > p:not(.error) {
@extend %auth-form-hr;
}
%auth-form-hr {
text-align: center;
position: relative;
}
%auth-form-hr span {
display: inline-block;
padding: 5px;
}
%auth-form-hr::before {
@extend %as-pseudo;
width: 100%;
position: absolute;
left: 0;
top: 50%;
z-index: -1;
}

View File

@ -1,12 +1,5 @@
%auth-form-hr {
text-transform: uppercase;
}
%auth-form-hr::before {
border-top: 1px solid rgb(var(--tone-gray-200));
}
/* This is to mask off the hr so it has a space */
/* in the center so if the background color of what the */
/* line is on is different, then this should be different */
%auth-form-hr span {
background-color: rgb(var(--tone-gray-000));
}
%auth-form em {
@extend %p3;
color: rgb(var(--tone-gray-500));
font-style: normal;
}

View File

@ -0,0 +1,20 @@
export default {
id: 'auth-form-tabs',
initial: 'token',
on: {
TOKEN: [
{
target: 'token',
},
],
SSO: [
{
target: 'sso',
},
],
},
states: {
token: {},
sso: {},
},
};

View File

@ -0,0 +1,53 @@
---
state: wip
---
# FormInput
Base component for making all types of form components.
This component should 'generally' not be used in application code, but instead
be used as a base component for creating application form components/elements.
This component should contain the shared functionality for all form
components, such as labels, errors, notes/messages/notices etc etc. Specific
input types should be provided using the `input` slot.
The following example shows how to create new form input components and
'generally' shouldn't be used in application code.
```hbs preview-template
<FormInput
@name="single"
@help="Help me if you can, I'm feeling down"
>
<:label>
Single Line Text Input
</:label>
<:input>
<input type="text" />
</:input>
</FormInput>
```
## Arguments
| Argument | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `String` | '' | An identifier for retriving values/errors etc for this input |
| `help` | `String` | | Provide some help text for the input (consider using `@validations` instead) |
| `validations` | `Object` | | A `validations` object |
| `chart` | `Object` | | A StateChart object (implementing `state` and `dispatch` to be passed to the underlying `validate` modifier |
### Slots
| Name | Description |
| --- | --- |
| `input` | Slot to hold the specific input element |
| `label` | The label to be rendered |
## See
- [Template Source Code](./index.hbs)
---

View File

@ -0,0 +1,25 @@
<label
class={{concat 'form-input' (if (get @chart.state.context.errors @name) ' has-error')}}
...attributes
>
<span>
{{yield to='label'}}
</span>
{{yield to='input'}}
{{#let
(or @validations.help @help)
as |help|}}
{{#if help}}
{{!- add an optional slot here called <:help>?-}}
<em>
{{help}}
</em>
{{/if}}
{{/let}}
<State @state={{@chart.state}} @matches="error">
{{!- add an optional slot here called <:alert/error/success>?-}}
<strong
role="alert"
>{{get (get @chart.state.context.errors @name) 'message'}}</strong>
</State>
</label>

View File

@ -263,7 +263,22 @@
</BlockSlot>
<BlockSlot @name="body">
<AuthForm as |authForm|>
<Ref @target={{this}} @name="authForm" @value={{authForm}} />
<Ref
@target={{this}}
@name="authForm"
@value={{authForm}}
/>
{{#if (can "use SSO")}}
<authForm.Method @matches="sso">
<OidcSelect
@dc={{@dc.Name}}
@nspace={{@nspace}}
@disabled={{authForm.disabled}}
@onchange={{authForm.submit}}
@onerror={{authForm.error}}
/>
</authForm.Method>
{{/if}}
</AuthForm>
</BlockSlot>
<BlockSlot @name="actions">

View File

@ -0,0 +1,37 @@
# OidcSelect
OidcSelect is a mostly template only form component specifically providing a
way for the user to select their OIDC provider for their available options
which can depend upon whether they have any OIDC providers confifured for
their partition. The necessary functionality/data retrieval is all composed
together using a StateChart to orchestrate the flow.
unlike most other components which require 'buckets' specifying, this
component **does not** require a `@partition` argument as this needs to be
provided by the user.
```hbs preview-template
<OidcSelect
@dc={{'dc-1'}}
@nspace={{'default'}}
@disabled={{false}}
@onchange={{noop}}
@onerror={{noop}}
/>
```
## Arguments
| Argument | Type | Default | Description |
| --- | --- | --- | --- |
| `dc` | `String` | | The name of the current datacenter |
| `nspace` | `String` | | The name of the current namespace |
| `onchange` | `Function` | | The action to fire when an oidc provider has been selected/changed |
## See
- [Component Source Code](./index.js)
- [Template Source Code](./index.hbs)
---

View File

@ -1,7 +1,23 @@
export default {
id: 'oidc-select',
initial: 'loading',
initial: 'idle',
on: {
RESET: [
{
target: 'idle',
},
],
},
states: {
idle: {
on: {
LOAD: [
{
target: 'loading',
},
],
},
},
loaded: {},
loading: {
on: {

View File

@ -1,48 +1,134 @@
<StateChart @src={{chart}} as |State Guard Action dispatch state|>
<Ref @target={{this}} @name="dispatch" @value={{dispatch}} />
<State @matches="loaded">
<div class="oidc-select" ...attributes>
{{#if (lt items.length 3)}}
<ul>
{{#each items as |item|}}
<li>
<button
disabled={{disabled}}
type="button" class={{concat item.Kind '-oidc-provider'}}
onclick={{action onchange item}}
>
Continue with {{or item.DisplayName item.Name}}{{#if (not-eq item.Namespace 'default')}} ({{item.Namespace}}){{/if}}
</button>
</li>
{{/each}}
</ul>
{{else}}
{{#let (or provider (object-at 0 items)) as |item|}}
<label>
<span>SSO Provider</span>
<PowerSelect
@disabled={{disabled}}
@onChange={{action (mut provider)}}
@selected={{item}}
@searchEnabled={{false}}
@options={{items}} as |item|>
<span class={{concat item.Kind '-oidc-provider'}}>
{{or item.DisplayName item.Name}}{{#if (not-eq item.Namespace 'default')}} ({{item.Namespace}}){{/if}}
</span>
</PowerSelect>
</label>
<button
disabled={{disabled}}
type="button"
onclick={{action onchange item}}
>
Log in
</button>
{{/let}}
{{/if}}
</div>
<StateChart
@src={{chart}}
as |State Guard ChartAction dispatch state|>
{{#let
(hash
State=State
Guard=Guard
Action=ChartAction
dispatch=dispatch
state=state
)
as |chart|}}
<div
class="oidc-select"
...attributes
>
<State @notMatches="idle">
<DataSource
@src={{uri '/${partition}/${nspace}/${dc}/oidc/providers'
(hash
partition=this.partition
nspace=@nspace
dc=@dc
)
}}
@onchange={{queue (action (mut this.items) value="data") (fn dispatch "SUCCESS")}}
@onerror={{queue (fn dispatch "RESET") @onerror}}
/>
</State>
<State @matches="loaded">
<Action
{{on 'click' (queue (set this 'partition' '') (fn dispatch "RESET"))}}
class="reset"
>
Choose different Admin Partition
</Action>
</State>
<StateChart
@src={{state-chart 'validate'}}
as |ignoredState ignoredGuard ignoredAction formDispatch state|>
<TextInput
@name="partition"
@label="Admin Partition"
@item={{this}}
@validations={{hash
partition=(array
(hash
test='^[a-zA-Z0-9]([a-zA-Z0-9-]{0,62}[a-zA-Z0-9])?$'
error='Name must be a valid DNS hostname.'
)
)
}}
@placeholder="Enter name of Admin Partition to log in to"
@oninput={{action (mut this.partition) value="target.value"}}
@chart={{hash
state=state
dispatch=formDispatch
}}
/>
{{! this belongs to the outer StateChart but we need }}
{{! to understand validation state }}
<State @matches="idle">
<Action
{{disabled (or (lt this.partition.length 1) (state-matches state "error"))}}
{{on "click" (fn dispatch "LOAD")}}
>
Choose provider
</Action>
</State>
</StateChart>
<State @matches="loading">
<div class="progress indeterminate"></div>
<Progress />
</State>
<State @matches="loaded">
{{#if (lt this.items.length 3)}}
<ul>
{{#each this.items as |item|}}
<li>
<Action
class={{concat item.Kind '-oidc-provider'}}
disabled={{@disabled}}
@type="button"
{{on 'click' (fn @onchange item)}}
>
Continue with {{or item.DisplayName item.Name}}{{#if (not-eq item.Namespace 'default')}} ({{item.Namespace}}){{/if}}
</Action>
</li>
{{/each}}
</ul>
{{else}}
{{#let (or this.provider (object-at 0 this.items)) as |item|}}
<OptionInput
@label="SSO Provider"
@name="provider"
@item={{this}}
@selected={{item}}
@items={{this.items}}
@onchange={{action (mut this.provider)}}
@disabled={{@disabled}}
>
<:option as |option|>
<span
class={{concat option.item.Kind '-oidc-provider'}}
>
{{or option.item.DisplayName option.item.Name}}{{#if (not-eq option.item.Namespace 'default')}} ({{option.item.Namespace}}){{/if}}
</span>
</:option>
</OptionInput>
<Action
@type="button"
{{disabled @disabled}}
{{on 'click' (fn @onchange item)}}
>
Log in
</Action>
{{/let}}
{{/if}}
</State>
</div>
{{/let}}
</StateChart>

View File

@ -1,20 +1,12 @@
import Component from '@ember/component';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import chart from './chart.xstate';
export default Component.extend({
tagName: '',
onchange: function() {},
onerror: function() {},
init: function() {
this._super(...arguments);
export default class OidcSelect extends Component {
@tracked partition = '';
constructor() {
super(...arguments);
this.chart = chart;
},
didReceiveAttrs: function() {
// This gets called no matter which attr has changed
// such as disabled, thing is once we are in loaded state
// it doesn't do anything anymore
if (typeof this.items !== 'undefined') {
this.dispatch('SUCCESS');
}
},
});
}
}

View File

@ -1,11 +1,15 @@
@import './skin';
@import './layout';
.oidc-select {
@extend %oidc-select;
}
%oidc-select label {
@extend %form-element;
}
%oidc-select button {
@extend %secondary-button;
%oidc-select button:not(.reset) {
@extend %primary-button;
}
%oidc-select button.reset {
@extend %anchor;
@extend %p3;
}
.oidc-select {
@extend %oidc-select;
}

View File

@ -5,3 +5,6 @@
%oidc-select .ember-power-select-trigger {
width: 100%;
}
%oidc-select button.reset {
float: right;
}

View File

@ -0,0 +1,50 @@
# OptionInput
Form component to be used for choosing options, both compacted form (coming
soon) and expanded form. Certain API decision are based on the usage of
`ember-power-select` which is currently used internally. This is likely to
change slightly at some point in the future.
```hbs preview-template
<OptionInput
@name="Choice"
@label="Choice of different options"
@item={{hash
Choice="selection"
}}
@selected={{or this.selected 'option 2'}}
@items={{array
'option 1'
'option 2'
'option 3'
'option 4'
}}
@onchange={{action (mut this.selected)}}
>
<:option as |option|>
<span>{{option.item}}</span>
</:option>
</OptionInput>
```
## Arguments
| Argument | Type | Default | Description |
| --- | --- | --- | --- |
| `item` | `Object` | | An object whose properties are to be edited |
| `name` | `String` | '' | An identifier for the property to be edited on the `item` |
| `label` | `String` | `@name` | A label to use to label the text input element |
| `placeholder` | `String` | | Equivalent to the HTML `placeholder=""` attribute |
| `help` | `String` | | Provide some help text for the input (consider using `@validations` instead) |
| `multiple` | `Boolean` | `false` | Set the OptionInput to be multiple choice (coming soon) |
| `expanded` | `Boolean` | `false` | Whether to use expanded radiobuttons/checkboxes or just a non-expanded select-like input |
| `validations` | `Object` | | A `validations` object to be passed to the underlying `validate` modifier |
| `chart` | `Object` | | A StateChart object (implementing `state` and `dispatch` to be passed to the underlying `validate` modifier |
| `onchange` | `Function` | | An event listener fired onchange of the input |
## See
- [Validate Modifier](../modifiers/validate.mdx)
- [Template Source Code](./index.hbs)
---

View File

@ -0,0 +1,36 @@
<FormInput
class="option-input type-select"
...attributes
@item={{@item}}
@placeholder={{@placeholder}}
@name={{@name}}
@label={{@label}}
@help={{@help}}
@validations={{@validations}}
@chart={{@chart}}
>
<:label>
{{!- add an optional slot here called <:label>-}}
{{or @label @name}}
</:label>
<:input>
{{#if @expanded}}
{{#if @multiple}}
{{! checkboxes }}
{{else}}
{{! radiobuttons }}
{{/if}}
{{else}}
<PowerSelect
@disabled={{@disabled}}
@onChange={{@onchange}}
@selected={{@selected}}
@searchEnabled={{false}}
@options={{@items}} as |item|>
{{yield (hash
item=item
) to='option'}}
</PowerSelect>
{{/if}}
</:input>
</FormInput>

View File

@ -0,0 +1,8 @@
# Progress
Simple Progress component in lieu of a reliable/styleable cross browser
`<progress />`.
```hbs preview-template
<Progress />
```

View File

@ -0,0 +1,4 @@
<div
class="progress indeterminate"
...attributes
></div>

View File

@ -1,6 +1,5 @@
---
class: ember
status: needs-love
state: needs-love
---
# TabNav
@ -15,11 +14,11 @@ Each item in the list should be a hash of `label`, `href` and `selected`.
generated via `is-href`
**Please note:** This component should probably be rebuilt using contextual
components and our `Action` component, alternatively this could be hand built
with native HTML using the same `nav/ul/li/a` pattern and you could just use
the CSS component to style it. Unless there is a reason to do this, this
component should be used pending a refactor (please remove this note once
refactored into contextual components using our `Action` component)
components, alternatively this could be hand built with native HTML using the
same `nav/ul/li/a` pattern and you could just use the CSS component to style
it. Unless there is a reason to do this, this component should be used pending
a refactor (please remove this note once refactored into contextual
components)
```hbs preview-template
<figure>

View File

@ -1,31 +1,47 @@
{{#let
(dom-position (set this 'style') offset=true)
"tab"
as |select name|}}
<nav
style={{{if selectedWidth (concat
'--selected-width:' selectedWidth ';'
'--selected-left:' selectedLeft ';'
'--selected-height:' selectedHeight ';'
'--selected-top:' selectedTop
style={{{if this.style (concat
'--selected-width:' this.style.width ';'
'--selected-left:' this.style.left ';'
'--selected-height:' this.style.height ';'
'--selected-top:' this.style.top
)
undefined
}}}
aria-label="Secondary"
class={{concat 'tab-nav' (if isAnimatable ' animatable' '')}}
id={{guid}}
class={{concat 'tab-nav' ' animatable'}}
...attributes
>
>
<ul>
{{#each items as |item|}}
<li
data-test-tab={{concat name '_' (if item.label (slugify item.label) (slugify item))}}
class={{if (or item.selected (eq selected (if item.label (slugify item.label) (slugify item)))) 'selected'}}
{{#each @items as |item|}}
<li
{{on 'click' (fn select)}}
{{did-upsert
(if item.selected
(fn select)
(noop)
)
@items.length
}}
data-test-tab={{concat name '_' (if item.label (slugify item.label) (slugify item))}}
class={{if (or item.selected (eq selected (if item.label (slugify item.label) (slugify item)))) 'selected'}}
>
{{#if item.href }}
<a href={{item.href}}>{{item.label}}</a>
{{else}}
<label role="tab" onkeydown={{action 'keydown'}} tabindex="0" aria-controls="radiogroup_{{name}}_{{if item.label (slugify item.label) (slugify item)}}_panel" for="radiogroup_{{name}}_{{if item.label (slugify item.label) (slugify item)}}" data-test-radiobutton="{{name}}_{{if item.label (slugify item.label) (slugify item)}}">
<a>{{item}}</a>
</label>
{{/if}}
</li>
<Action
{{on 'click'
(if (not-eq @onclick undefined)
(fn @onclick (uppercase item.label))
(noop)
)
}}
@href={{item.href}}
>
{{item.label}}
</Action>
</li>
{{/each}}
</ul>
</nav>
</nav>
{{/let}}

View File

@ -1,44 +1,3 @@
import Component from '@ember/component';
import { setProperties, set } from '@ember/object';
import { inject as service } from '@ember/service';
import { schedule } from '@ember/runloop';
import Component from '@glimmer/component';
const ENTER = 13;
const SELECTED = 'li.selected';
export default Component.extend({
name: 'tab',
tagName: '',
dom: service('dom'),
isAnimatable: false,
init: function() {
this._super(...arguments);
this.guid = this.dom.guid(this);
},
didInsertElement: function() {
this._super(...arguments);
this.$nav = this.dom.element(`#${this.guid}`);
this.select(this.dom.element(SELECTED, this.$nav));
set(this, 'isAnimatable', true);
},
didUpdateAttrs: function() {
schedule('afterRender', () => this.select(this.dom.element(SELECTED, this.$nav)));
},
select: function($el) {
if (!$el) {
return;
}
setProperties(this, {
selectedWidth: $el.offsetWidth,
selectedLeft: $el.offsetLeft,
selectedHeight: $el.offsetHeight,
selectedTop: $el.offsetTop,
});
},
actions: {
keydown: function(e) {
if (e.keyCode === ENTER) {
e.target.dispatchEvent(new MouseEvent('click'));
}
},
},
});
export default class TabNav extends Component {}

View File

@ -6,36 +6,21 @@
%tab-nav.animatable {
@extend %with-animated-tab-selection;
}
.tab-section {
@extend %tab-section;
/* this keeps in-tab-section toolbars flush to the top, see Node Detail > Services */
margin-top: 0 !important;
}
%with-animated-tab-selection ul::after,
%tab-button-selected {
@extend %frame-blue-300;
}
%tab-nav li a {
%tab-nav li > * {
@extend %tab-button;
}
%tab-nav li:not(.selected) a:hover,
%tab-nav li:not(.selected) a:focus {
%tab-nav li:not(.selected) > *:hover,
%tab-nav li:not(.selected) > *:focus {
@extend %tab-button-intent;
}
%tab-nav li:not(.selected) a:active {
%tab-nav li:not(.selected) > *:active {
@extend %tab-button-active;
}
/* TODO: need to add an empty class here */
%tab-nav .selected a {
%tab-nav .selected > * {
@extend %tab-button-selected;
}
%display-state,
%display-state + * {
display: none;
}
%display-state:checked + * {
display: block;
}
%tab-section > input[type='radio'] {
@extend %display-state;
}

View File

@ -1,13 +1,13 @@
%tab-nav ul {
list-style-type: none;
}
%tab-nav label {
cursor: pointer;
}
%tab-button {
white-space: nowrap;
text-decoration: none;
}
%tab-button:not(:disabled) {
cursor: pointer;
}
%tab-nav {
/* %frame-transparent-something */
border-bottom: var(--decor-border-100);

View File

@ -37,6 +37,7 @@ changed to also accept slots for specifying specific parts of the component.
| `expanded` | `Boolean` | `false` | Whether to use an expanded textarea or just a normal single line input |
| `validations` | `Object` | | A `validations` object to be passed to the underlying `validate` modifier |
| `chart` | `Object` | | A StateChart object (implementing `state` and `dispatch` to be passed to the underlying `validate` modifier |
| `oninput` | `Function` | | An event listener fired oninput to the text input |
## See

View File

@ -1,12 +1,19 @@
<label
class={{concat 'text-input' ' type-text' (if (get @chart.state.context.errors @name) ' has-error')}}
<FormInput
class={{concat 'text-input' ' type-text'}}
...attributes
@item={{@item}}
@placeholder={{@placeholder}}
@name={{@name}}
@label={{@label}}
@help={{@help}}
@validations={{@validations}}
@chart={{@chart}}
>
<span>
<:label>
{{!- add an optional slot here called <:label>-}}
{{or @label @name}}
</span>
{{!- add an optional slot here called <:input>?-}}
</:label>
<:input>
{{#if @expanded}}
<textarea
{{validate @item
@ -29,20 +36,5 @@
placeholder={{or @placeholder}}
/>
{{/if}}
{{#let
(or @validations.help @help)
as |help|}}
{{#if help}}
{{!- add an optional slot here called <:help>?-}}
<em>
{{help}}
</em>
{{/if}}
{{/let}}
<State @state={{@chart.state}} @matches="error">
{{!- add an optional slot here called <:alert/error/success>?-}}
<strong
role="alert"
>{{get (get @chart.state.context.errors @name) 'message'}}</strong>
</State>
</label>
</:input>
</FormInput>

View File

@ -1,18 +1,30 @@
import Helper from '@ember/component/helper';
export default class DomPosition extends Helper {
compute([target], { from }) {
if (typeof target === 'function') {
return entry => {
const $target = entry.target;
let rect = $target.getBoundingClientRect();
if (typeof from !== 'undefined') {
const fromRect = from.getBoundingClientRect();
rect.x = rect.x - fromRect.x;
rect.y = rect.y - fromRect.y;
compute([target], { from, offset = false }) {
return e => {
if (typeof target === 'function') {
let rect;
let $el;
if (offset) {
$el = e.currentTarget;
rect = {
width: $el.offsetWidth,
left: $el.offsetLeft,
height: $el.offsetHeight,
top: $el.offsetTop,
};
} else {
$el = e.target;
rect = $el.getBoundingClientRect();
if (typeof from !== 'undefined') {
const fromRect = from.getBoundingClientRect();
rect.x = rect.x - fromRect.x;
rect.y = rect.y - fromRect.y;
}
}
return target(rect);
};
}
}
};
}
}

View File

@ -206,19 +206,31 @@ export default class FSMWithOptionalLocation {
withOptional = false;
break;
}
if(this.router.currentRouteName.startsWith('docs.')) {
if (this.router.currentRouteName.startsWith('docs.')) {
// If we are in docs, then add a default dc as there won't be one in the
// URL
params.unshift(env('CONSUL_DATACENTER_PRIMARY'));
if(routeName.startsWith('dc')) {
if (routeName.startsWith('dc')) {
// if its an app URL replace it with debugging instead of linking
return `console://${routeName} <= ${JSON.stringify(params)}`;
}
}
const router = this.router._routerMicrolib;
const url = router.generate(routeName, ...params, {
queryParams: {},
});
let url;
try {
url = router.generate(routeName, ...params, {
queryParams: {},
});
} catch (e) {
// if the previous generation throws due to params not being available
// its probably due to the view wanting to re-render even though we are
// leaving the view and the router has already moved the state to old
// state so try again with the old state to avoid errors
params = Object.values(router.oldState.params).reduce((prev, item) => {
return prev.concat(Object.keys(item).length > 0 ? item : []);
}, []);
url = router.generate(routeName, ...params);
}
return this.formatURL(url, hash, withOptional);
}
@ -227,7 +239,7 @@ export default class FSMWithOptionalLocation {
* performs an ember transition/refresh and browser location update using that
*/
transitionTo(url) {
if(this.router.currentRouteName.startsWith('docs') && url.startsWith('console://')) {
if (this.router.currentRouteName.startsWith('docs') && url.startsWith('console://')) {
console.log(`location.transitionTo: ${url.substr(10)}`);
return true;
}
@ -241,7 +253,7 @@ export default class FSMWithOptionalLocation {
// this.setURL(url);
} else {
const currentOptional = this.optionalParams();
if(previousOptional.some(([key, value]) => currentOptional[key] !== value)) {
if (previousOptional.some(([key, value]) => currentOptional[key] !== value)) {
// an optional parameter change and a normal param change as the Ember
// URLs are different and we know the optional params changed
// TODO: Consider changing the above previousURL === transitionURL to

View File

@ -0,0 +1,46 @@
import { setModifierManager, capabilities } from '@ember/modifier';
import { gte } from 'ember-compatibility-helpers';
const createEventLike = state => {
return {
target: state.element,
currentTarget: state.element,
};
};
export default setModifierManager(
() => ({
capabilities: capabilities(gte('3.22.0') ? '3.22' : '3.13', { disableAutoTracking: true }),
createModifier() {
return { element: null };
},
installModifier(state, element, args) {
state.element = element;
if (gte('3.22.0')) {
// Consume individual properties to entangle tracking.
// https://github.com/emberjs/ember.js/issues/19277
// https://github.com/ember-modifier/ember-modifier/pull/63#issuecomment-815908201
args.positional.forEach(() => {});
args.named && Object.values(args.named);
}
const [fn, ...positional] = args.positional;
fn(createEventLike(state), positional, args.named);
},
updateModifier(state, args) {
if (gte('3.22.0')) {
// Consume individual properties to entangle tracking.
// https://github.com/emberjs/ember.js/issues/19277
// https://github.com/ember-modifier/ember-modifier/pull/63#issuecomment-815908201
args.positional.forEach(() => {});
args.named && Object.values(args.named);
}
const [fn, ...positional] = args.positional;
fn(createEventLike(state), positional, args.named);
},
destroyModifier() {},
}),
class DidUpsertModifier {}
);

View File

@ -0,0 +1,31 @@
# did-upsert
Modifier that is called when a DOM node is inserted and/or an argument is
updated.
Additionally the callback function provided should expect an event shaped
object rather than a reference to a DOM node itself, therefore the DOM node
can be obtained by referencing `target` or `currentTarget` instead. This means
that you can use the same callback function for both `{{on 'click'}}`
modifiers and `{{did-upsert}}` modifiers. The one dowbside is that the
signature of functions used for `did-upsert` are slightly different than when
you use `did-insert/did-update`, but moving forwards we are more likely to
make `did-insert/did-update` use a more standard based signature (or some
other approach to make things consistent)
```hbs
<div
{{did-upsert this.callback @arrayThatMightGetAddedToTODetectAnUpdate.length}}
>
</div>
```
```javascript
callback(e) {
console.log(e.currentTarget);
console.log(e.target);
}
```
Other than the above exception, the modifer works the same as the
`did-insert/did-update` modifiers.

View File

@ -0,0 +1,10 @@
import Service from 'ember-can/services/can';
export default class CanService extends Service {
parse(str) {
// It's nicer to talk about SSO but technically its part of the authMethod
// ability, we probably only need 'use SSO' but if we need more, reasses
// the `replace`
return super.parse(str.replace('use SSO', ' use authMethods'));
}
}

View File

@ -21,7 +21,14 @@ export default class OidcProviderService extends RepositoryService {
@dataSource('/:partition/:ns/:dc/oidc/providers')
async findAllByDatacenter() {
return super.findAllByDatacenter(...arguments);
const res = await super.findAllByDatacenter(...arguments);
if (res.length === 0) {
const err = new Error('Not found');
err.statusCode = 404;
this.store.adapterFor(this.getModelName()).error(err);
return;
}
return res;
}
@dataSource('/:partition/:ns/:dc/oidc/provider/:id')

View File

@ -77,11 +77,11 @@ as |item tomography|}}
<TabNav @items={{
compact
(array
(hash label="Health Checks" href=(href-to "dc.nodes.show.healthchecks") selected=(is-href "dc.nodes.show.healthchecks"))
(hash label="Service Instances" href=(href-to "dc.nodes.show.services") selected=(is-href "dc.nodes.show.services"))
(if tomography.distances (hash label="Round Trip Time" href=(href-to "dc.nodes.show.rtt") selected=(is-href "dc.nodes.show.rtt")) '')
(hash label="Lock Sessions" href=(href-to "dc.nodes.show.sessions") selected=(is-href "dc.nodes.show.sessions"))
(hash label="Metadata" href=(href-to "dc.nodes.show.metadata") selected=(is-href "dc.nodes.show.metadata"))
(hash label="Health Checks" href=(href-to "dc.nodes.show.healthchecks") selected=(is-href "dc.nodes.show.healthchecks"))
(hash label="Service Instances" href=(href-to "dc.nodes.show.services") selected=(is-href "dc.nodes.show.services"))
(if tomography.distances (hash label="Round Trip Time" href=(href-to "dc.nodes.show.rtt") selected=(is-href "dc.nodes.show.rtt")) '')
(hash label="Lock Sessions" href=(href-to "dc.nodes.show.sessions") selected=(is-href "dc.nodes.show.sessions"))
(hash label="Metadata" href=(href-to "dc.nodes.show.metadata") selected=(is-href "dc.nodes.show.metadata"))
)
}}/>
</BlockSlot>

View File

@ -110,6 +110,7 @@
"ember-cli-uglify": "^3.0.0",
"ember-cli-yadda": "^0.6.0",
"ember-collection": "^1.0.0-alpha.9",
"ember-compatibility-helpers": "^1.2.5",
"ember-composable-helpers": "~4.0.0",
"ember-data": "~3.20.4",
"ember-data-model-fragments": "5.0.0-beta.0",

View File

@ -1167,6 +1167,15 @@
ember-cli-babel "^7.10.0"
ember-modifier-manager-polyfill "^1.1.0"
"@ember/render-modifiers@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@ember/render-modifiers/-/render-modifiers-2.0.0.tgz#7106928078c6463bc6ee3cbffb6d71dbb8602145"
integrity sha512-FbvowKEnYx102MaNMrePBC7RCmuf3BaqPKbp6QP7S6oJaDMuLrGblXW4TxOrE93C6II+6D4QNB4WFGuPeQ3ZBg==
dependencies:
ember-cli-babel "^7.26.6"
ember-compatibility-helpers "^1.2.5"
ember-modifier-manager-polyfill "^1.2.0"
"@ember/test-helpers@^1.7.1":
version "1.7.2"
resolved "https://registry.yarnpkg.com/@ember/test-helpers/-/test-helpers-1.7.2.tgz#5b128dc5f6524c3850abf52668e6bd4fda401194"
@ -1233,7 +1242,7 @@
resolve "^1.8.1"
semver "^7.3.2"
"@embroider/macros@0.41.0", "@embroider/macros@^0.39.0 || ^0.40.0 || ^0.41.0":
"@embroider/macros@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@embroider/macros/-/macros-0.41.0.tgz#3e78b6f388d7229906abf4c75edfff8bb0208aca"
integrity sha512-QISzwEEfLsskZeL0jyZDs1RoQSotwBWj+4upTogNHuxQP5j/9H3IMG/3QB1gh8GEpbudATb/cS4NDYK3UBxufw==
@ -1245,6 +1254,19 @@
resolve "^1.8.1"
semver "^7.3.2"
"@embroider/macros@0.47.2", "@embroider/macros@^0.47.0":
version "0.47.2"
resolved "https://registry.yarnpkg.com/@embroider/macros/-/macros-0.47.2.tgz#23cbe92cac3c24747f054e1eea2a22538bf7ebd0"
integrity sha512-ViNWluJCeM5OPlM3rs8kdOz3RV5rpfXX5D2rDnc/q86xRS0xf4NFEjYRV7W6fBcD0b3v5jSHDTwrjq9Kee4rHg==
dependencies:
"@embroider/shared-internals" "0.47.2"
assert-never "^1.2.1"
ember-cli-babel "^7.26.6"
find-up "^5.0.0"
lodash "^4.17.21"
resolve "^1.20.0"
semver "^7.3.2"
"@embroider/shared-internals@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@embroider/shared-internals/-/shared-internals-0.41.0.tgz#2553f026d4f48ea1fd11235501feb63bf49fa306"
@ -1258,7 +1280,20 @@
semver "^7.3.2"
typescript-memoize "^1.0.0-alpha.3"
"@embroider/util@^0.39.0 || ^0.40.0 || ^0.41.0", "@embroider/util@^0.39.1 || ^0.40.0 || ^0.41.0":
"@embroider/shared-internals@0.47.2":
version "0.47.2"
resolved "https://registry.yarnpkg.com/@embroider/shared-internals/-/shared-internals-0.47.2.tgz#24e9fa0dd9c529d5c996ee1325729ea08d1fa19f"
integrity sha512-SxdZYjAE0fiM5zGDz+12euWIsQZ1tsfR1k+NKmiWMyLhA5T3pNgbR2/Djvx/cVIxOtEavGGSllYbzRKBtV4xMg==
dependencies:
babel-import-util "^0.2.0"
ember-rfc176-data "^0.3.17"
fs-extra "^9.1.0"
lodash "^4.17.21"
resolve-package-path "^4.0.1"
semver "^7.3.5"
typescript-memoize "^1.0.1"
"@embroider/util@^0.39.1 || ^0.40.0 || ^0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@embroider/util/-/util-0.41.0.tgz#5324cb4742aa4ed8d613c4f88a466f73e4e6acc1"
integrity sha512-ytA3J/YfQh7FEUEBwz3ezTqQNm/S5et5rZw3INBIy4Ak4x0NXV/VXLjyL8mv3txL8fGknZTBdXEhDsHUKIq8SQ==
@ -1267,6 +1302,15 @@
broccoli-funnel "^3.0.5"
ember-cli-babel "^7.23.1"
"@embroider/util@^0.47.0":
version "0.47.2"
resolved "https://registry.yarnpkg.com/@embroider/util/-/util-0.47.2.tgz#d06497b4b84c07ed9c7b628293bb019c533f4556"
integrity sha512-g9OqnFJPktGu9NS0Ug3Pxz1JE3jeDceeVE4IrlxDrVmBXMA/GrBvpwjolWgl6jh97cMJyExdz62jIvPHV4256Q==
dependencies:
"@embroider/macros" "0.47.2"
broccoli-funnel "^3.0.5"
ember-cli-babel "^7.23.1"
"@eslint/eslintrc@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.0.tgz#99cc0a0584d72f1df38b900fb062ba995f395547"
@ -2281,7 +2325,7 @@ asn1@~0.2.3:
dependencies:
safer-buffer "~2.1.0"
assert-never@^1.1.0:
assert-never@^1.1.0, assert-never@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe"
integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==
@ -2570,6 +2614,11 @@ babel-helpers@^6.24.1:
babel-runtime "^6.22.0"
babel-template "^6.24.1"
babel-import-util@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/babel-import-util/-/babel-import-util-0.2.0.tgz#b468bb679919601a3570f9e317536c54f2862e23"
integrity sha512-CtWYYHU/MgK88rxMrLfkD356dApswtR/kWZ/c6JifG1m10e7tBBrs/366dFzWMAoqYmG5/JSh+94tUSpIwh+ag==
babel-loader@^8.0.6, babel-loader@^8.1.0:
version "8.2.2"
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81"
@ -2636,6 +2685,16 @@ babel-plugin-ember-modules-api-polyfill@^3.2.0, babel-plugin-ember-modules-api-p
dependencies:
ember-rfc176-data "^0.3.17"
babel-plugin-ember-template-compilation@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/babel-plugin-ember-template-compilation/-/babel-plugin-ember-template-compilation-1.0.1.tgz#64baf434ff1b751c6292936f8b9eb75a2f8149dc"
integrity sha512-V/kY6CDyUNrl5Kx6UPKUPhzSKNfdrxNii+S5zK4dgJvVyoxFv7Ykg06Ct/yskY0LkA4wUPdYN7JOBtYJwHk2sg==
dependencies:
babel-import-util "^0.2.0"
line-column "^1.0.2"
magic-string "^0.25.7"
string.prototype.matchall "^4.0.5"
babel-plugin-filter-imports@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/babel-plugin-filter-imports/-/babel-plugin-filter-imports-4.0.0.tgz#068f8da15236a96a9602c36dc6f4a6eeca70a4f4"
@ -2661,6 +2720,17 @@ babel-plugin-htmlbars-inline-precompile@^5.0.0:
dependencies:
babel-plugin-ember-modules-api-polyfill "^3.4.0"
babel-plugin-htmlbars-inline-precompile@^5.3.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/babel-plugin-htmlbars-inline-precompile/-/babel-plugin-htmlbars-inline-precompile-5.3.1.tgz#5ba272e2e4b6221522401f5f1d98a73b1de38787"
integrity sha512-QWjjFgSKtSRIcsBhJmEwS2laIdrA6na8HAlc/pEAhjHgQsah/gMiBFRZvbQTy//hWxR4BMwV7/Mya7q5H8uHeA==
dependencies:
babel-plugin-ember-modules-api-polyfill "^3.5.0"
line-column "^1.0.2"
magic-string "^0.25.7"
parse-static-imports "^1.1.0"
string.prototype.matchall "^4.0.5"
babel-plugin-istanbul@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765"
@ -5437,20 +5507,20 @@ ember-auto-import@^1.5.2, ember-auto-import@^1.5.3, ember-auto-import@^1.6.0:
webpack "^4.43.0"
ember-basic-dropdown@^3.0.16:
version "3.0.19"
resolved "https://registry.yarnpkg.com/ember-basic-dropdown/-/ember-basic-dropdown-3.0.19.tgz#e15e71097cbcbc585e85c2c5cf677a6434edb1d5"
integrity sha512-5mZ4hbfGLd+TrFAp0JsfcpIb10zqF60SorKc1Bsm29kJF2wy8p0JUXMb21VVF7+phkrRFYbcXy5enFc8qdm4xw==
version "3.0.21"
resolved "https://registry.yarnpkg.com/ember-basic-dropdown/-/ember-basic-dropdown-3.0.21.tgz#5711d071966919c9578d2d5ac2c6dcadbb5ea0e0"
integrity sha512-Wu9hJWyqorKo+ZT2PMSIO1BxAeAdaiIC2IjSic0+HcKjmMU47botvG0xbxlprimOWaS9vM+nHat6Pt3xPvcB0A==
dependencies:
"@ember/render-modifiers" "^1.0.2"
"@embroider/macros" "^0.39.0 || ^0.40.0 || ^0.41.0"
"@embroider/util" "^0.39.0 || ^0.40.0 || ^0.41.0"
"@ember/render-modifiers" "^2.0.0"
"@embroider/macros" "^0.47.0"
"@embroider/util" "^0.47.0"
"@glimmer/component" "^1.0.4"
"@glimmer/tracking" "^1.0.4"
ember-cli-babel "^7.23.1"
ember-cli-htmlbars "^5.7.0"
ember-cli-babel "^7.26.6"
ember-cli-htmlbars "^6.0.0"
ember-cli-typescript "^4.1.0"
ember-element-helper "^0.5.2"
ember-maybe-in-element "^2.0.2"
ember-element-helper "^0.5.5"
ember-maybe-in-element "^2.0.3"
ember-style-modifier "^0.6.0"
ember-truth-helpers "^2.1.0 || ^3.0.0"
@ -5556,6 +5626,39 @@ ember-cli-babel@^6.0.0, ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.11.0,
ember-cli-version-checker "^2.1.2"
semver "^5.5.0"
ember-cli-babel@^7.26.6:
version "7.26.6"
resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-7.26.6.tgz#322fbbd3baad9dd99e3276ff05bc6faef5e54b39"
integrity sha512-040svtfj2RC35j/WMwdWJFusZaXmNoytLAMyBDGLMSlRvznudTxZjGlPV6UupmtTBApy58cEF8Fq4a+COWoEmQ==
dependencies:
"@babel/core" "^7.12.0"
"@babel/helper-compilation-targets" "^7.12.0"
"@babel/plugin-proposal-class-properties" "^7.13.0"
"@babel/plugin-proposal-decorators" "^7.13.5"
"@babel/plugin-transform-modules-amd" "^7.13.0"
"@babel/plugin-transform-runtime" "^7.13.9"
"@babel/plugin-transform-typescript" "^7.13.0"
"@babel/polyfill" "^7.11.5"
"@babel/preset-env" "^7.12.0"
"@babel/runtime" "7.12.18"
amd-name-resolver "^1.3.1"
babel-plugin-debug-macros "^0.3.4"
babel-plugin-ember-data-packages-polyfill "^0.1.2"
babel-plugin-ember-modules-api-polyfill "^3.5.0"
babel-plugin-module-resolver "^3.2.0"
broccoli-babel-transpiler "^7.8.0"
broccoli-debug "^0.6.4"
broccoli-funnel "^2.0.2"
broccoli-source "^2.1.2"
clone "^2.1.2"
ember-cli-babel-plugin-helpers "^1.1.1"
ember-cli-version-checker "^4.1.0"
ensure-posix-path "^1.0.2"
fixturify-project "^1.10.0"
resolve-package-path "^3.1.0"
rimraf "^3.0.1"
semver "^5.5.0"
ember-cli-code-coverage@^1.0.0-beta.4:
version "1.0.2"
resolved "https://registry.yarnpkg.com/ember-cli-code-coverage/-/ember-cli-code-coverage-1.0.2.tgz#615fc7af8bc7d9388a28371c2825c224a936d73f"
@ -5637,7 +5740,7 @@ ember-cli-htmlbars@^4.0.5, ember-cli-htmlbars@^4.2.1, ember-cli-htmlbars@^4.2.3,
strip-bom "^4.0.0"
walk-sync "^2.0.2"
ember-cli-htmlbars@^5.0.0, ember-cli-htmlbars@^5.1.0, ember-cli-htmlbars@^5.1.2, ember-cli-htmlbars@^5.2.0, ember-cli-htmlbars@^5.3.1, ember-cli-htmlbars@^5.6.3, ember-cli-htmlbars@^5.7.0:
ember-cli-htmlbars@^5.0.0, ember-cli-htmlbars@^5.1.0, ember-cli-htmlbars@^5.1.2, ember-cli-htmlbars@^5.2.0, ember-cli-htmlbars@^5.3.1, ember-cli-htmlbars@^5.6.3:
version "5.7.1"
resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-5.7.1.tgz#eb5b88c7d9083bc27665fb5447a9b7503b32ce4f"
integrity sha512-9laCgL4tSy48orNoQgQKEHp93MaqAs9ZOl7or5q+8iyGGJHW6sVXIYrVv5/5O9HfV6Ts8/pW1rSoaeKyLUE+oA==
@ -5659,6 +5762,27 @@ ember-cli-htmlbars@^5.0.0, ember-cli-htmlbars@^5.1.0, ember-cli-htmlbars@^5.1.2,
strip-bom "^4.0.0"
walk-sync "^2.2.0"
ember-cli-htmlbars@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-6.0.0.tgz#9d0b67c0f107467b6c8ecdc47d64e877489841bf"
integrity sha512-7h9Lb1kfvLecMUOX8wCbwjzCsgXdNDs8qpOsDuKV6YaGS9jDZHu4P5xTYLX78YepEUnwOw1atCYWzBUsJHWrzA==
dependencies:
"@ember/edition-utils" "^1.2.0"
babel-plugin-ember-template-compilation "^1.0.0"
babel-plugin-htmlbars-inline-precompile "^5.3.0"
broccoli-debug "^0.6.5"
broccoli-persistent-filter "^3.1.2"
broccoli-plugin "^4.0.3"
ember-cli-version-checker "^5.1.2"
fs-tree-diff "^2.0.1"
hash-for-dep "^1.5.1"
heimdalljs-logger "^0.1.10"
json-stable-stringify "^1.0.1"
semver "^7.3.4"
silent-error "^1.1.1"
strip-bom "^4.0.0"
walk-sync "^2.2.0"
ember-cli-inject-live-reload@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/ember-cli-inject-live-reload/-/ember-cli-inject-live-reload-2.0.2.tgz#95edb543b386239d35959e5ea9579f5382976ac7"
@ -6024,6 +6148,16 @@ ember-compatibility-helpers@^1.1.1, ember-compatibility-helpers@^1.1.2, ember-co
ember-cli-version-checker "^5.1.1"
semver "^5.4.1"
ember-compatibility-helpers@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.5.tgz#b8363b1d5b8725afa9a4fe2b2986ac28626c6f23"
integrity sha512-7cddkQQp8Rs2Mqrj0xqZ0uO7eC9tBCKyZNcP2iE1RxQqOGPv8fiPkj1TUeidUB/Qe80lstoVXWMEuqqhW7Yy9A==
dependencies:
babel-plugin-debug-macros "^0.2.0"
ember-cli-version-checker "^5.1.1"
fs-extra "^9.1.0"
semver "^5.4.1"
ember-composable-helpers@~4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/ember-composable-helpers/-/ember-composable-helpers-4.0.0.tgz#856cf4d86f2245feeb69ae1684e5a58ec742fcca"
@ -6114,7 +6248,7 @@ ember-destroyable-polyfill@^2.0.2:
ember-cli-version-checker "^5.1.1"
ember-compatibility-helpers "^1.2.1"
ember-element-helper@^0.5.2:
ember-element-helper@^0.5.5:
version "0.5.5"
resolved "https://registry.yarnpkg.com/ember-element-helper/-/ember-element-helper-0.5.5.tgz#4a9ecb4dce57ee7f5ceb868a53c7b498c729f056"
integrity sha512-Tu3hsI+/mjHBUvw62Qi+YDZtKkn59V66CjwbgfNTZZ7aHf4gFm1ow4zJ4WLnpnie8p9FvOmIUxwl5HvgPJIcFA==
@ -6269,7 +6403,7 @@ ember-maybe-import-regenerator@^0.1.6:
ember-cli-babel "^6.0.0-beta.4"
regenerator-runtime "^0.9.5"
ember-maybe-in-element@^2.0.2:
ember-maybe-in-element@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/ember-maybe-in-element/-/ember-maybe-in-element-2.0.3.tgz#640ea56b492bdacd1c41c128c2163d933c18c3ec"
integrity sha512-XKuBYPYELwsEmDnJXI7aNSZtt/SKGgRZNMFhASODLz7j0OHSNrcJtjo5Wam/alxIjUIYVjEnMnOzqBLMfJnQkQ==
@ -6779,6 +6913,32 @@ es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2:
string.prototype.trimstart "^1.0.4"
unbox-primitive "^1.0.0"
es-abstract@^1.19.1:
version "1.19.1"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3"
integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==
dependencies:
call-bind "^1.0.2"
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
get-intrinsic "^1.1.1"
get-symbol-description "^1.0.0"
has "^1.0.3"
has-symbols "^1.0.2"
internal-slot "^1.0.3"
is-callable "^1.2.4"
is-negative-zero "^2.0.1"
is-regex "^1.1.4"
is-shared-array-buffer "^1.0.1"
is-string "^1.0.7"
is-weakref "^1.0.1"
object-inspect "^1.11.0"
object-keys "^1.1.1"
object.assign "^4.1.2"
string.prototype.trimend "^1.0.4"
string.prototype.trimstart "^1.0.4"
unbox-primitive "^1.0.1"
es-get-iterator@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7"
@ -7695,7 +7855,7 @@ fs-extra@^8.0.0, fs-extra@^8.0.1, fs-extra@^8.1.0:
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-extra@^9.0.0, fs-extra@^9.0.1:
fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
@ -7875,6 +8035,14 @@ get-stream@^5.0.0:
dependencies:
pump "^3.0.0"
get-symbol-description@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==
dependencies:
call-bind "^1.0.2"
get-intrinsic "^1.1.1"
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@ -8123,7 +8291,7 @@ has-ansi@^3.0.0:
dependencies:
ansi-regex "^3.0.0"
has-bigints@^1.0.0:
has-bigints@^1.0.0, has-bigints@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
@ -8172,6 +8340,13 @@ has-to-string-tag-x@^1.2.0:
dependencies:
has-symbol-support-x "^1.4.1"
has-tostringtag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
dependencies:
has-symbols "^1.0.2"
has-unicode@^2.0.0, has-unicode@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@ -8629,6 +8804,15 @@ inquirer@^7.0.1:
strip-ansi "^6.0.0"
through "^2.3.6"
internal-slot@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==
dependencies:
get-intrinsic "^1.1.0"
has "^1.0.3"
side-channel "^1.0.4"
internmap@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95"
@ -8756,6 +8940,11 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.3:
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e"
integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==
is-callable@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
is-core-module@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
@ -8950,6 +9139,14 @@ is-regex@^1.1.1, is-regex@^1.1.2:
call-bind "^1.0.2"
has-symbols "^1.0.1"
is-regex@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
dependencies:
call-bind "^1.0.2"
has-tostringtag "^1.0.0"
is-regexp@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
@ -8965,6 +9162,11 @@ is-set@^2.0.1, is-set@^2.0.2:
resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec"
integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==
is-shared-array-buffer@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6"
integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==
is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
@ -8980,6 +9182,13 @@ is-string@^1.0.5:
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==
is-string@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
dependencies:
has-tostringtag "^1.0.0"
is-symbol@^1.0.2, is-symbol@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
@ -9020,6 +9229,13 @@ is-weakmap@^2.0.1:
resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2"
integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==
is-weakref@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2"
integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==
dependencies:
call-bind "^1.0.0"
is-weakset@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.1.tgz#e9a0af88dbd751589f5e50d80f4c98b780884f83"
@ -9459,6 +9675,14 @@ license-checker@^25.0.1:
spdx-satisfies "^4.0.0"
treeify "^1.1.0"
line-column@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2"
integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI=
dependencies:
isarray "^1.0.0"
isobject "^2.0.0"
lines-and-columns@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
@ -9849,6 +10073,13 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
magic-string@^0.25.7:
version "0.25.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
dependencies:
sourcemap-codec "^1.4.4"
make-dir@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
@ -10758,6 +10989,11 @@ object-hash@^1.3.1:
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df"
integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==
object-inspect@^1.11.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
object-inspect@^1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a"
@ -11120,6 +11356,11 @@ parse-passwd@^1.0.0:
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
parse-static-imports@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/parse-static-imports/-/parse-static-imports-1.1.0.tgz#ae2f18f18da1a993080ae406a5219455c0bbad5d"
integrity sha512-HlxrZcISCblEV0lzXmAHheH/8qEkKgmqkdxyHTPbSqsTUV8GzqmN1L+SSti+VbNPfbBO3bYLPHDiUs2avbAdbA==
parse5@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
@ -11799,7 +12040,7 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
regexp.prototype.flags@^1.3.0:
regexp.prototype.flags@^1.3.0, regexp.prototype.flags@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26"
integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==
@ -12096,6 +12337,13 @@ resolve-package-path@^3.1.0:
path-root "^0.1.1"
resolve "^1.17.0"
resolve-package-path@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/resolve-package-path/-/resolve-package-path-4.0.3.tgz#31dab6897236ea6613c72b83658d88898a9040aa"
integrity sha512-SRpNAPW4kewOaNUt8VPqhJ0UMxawMwzJD8V7m1cJfdSTK9ieZwS6K7Dabsm4bmLFM96Z5Y/UznrpG5kt1im8yA==
dependencies:
path-root "^0.1.1"
resolve-path@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7"
@ -12367,6 +12615,13 @@ semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4:
dependencies:
lru-cache "^6.0.0"
semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
dependencies:
lru-cache "^6.0.0"
send@0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
@ -12725,6 +12980,11 @@ source-map@~0.1.x:
dependencies:
amdefine ">=0.0.4"
sourcemap-codec@^1.4.4:
version "1.4.8"
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
sourcemap-validator@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/sourcemap-validator/-/sourcemap-validator-1.1.1.tgz#3d7d8a399ccab09c1fedc510d65436e25b1c386b"
@ -12941,6 +13201,20 @@ string-width@^4.1.0, string-width@^4.2.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
string.prototype.matchall@^4.0.5:
version "4.0.6"
resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa"
integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.3"
es-abstract "^1.19.1"
get-intrinsic "^1.1.1"
has-symbols "^1.0.2"
internal-slot "^1.0.3"
regexp.prototype.flags "^1.3.1"
side-channel "^1.0.4"
string.prototype.padend@^3.0.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz#6858ca4f35c5268ebd5e8615e1327d55f59ee311"
@ -13617,6 +13891,11 @@ typescript-memoize@^1.0.0-alpha.3:
resolved "https://registry.yarnpkg.com/typescript-memoize/-/typescript-memoize-1.0.0.tgz#ad3b0e7e5a411ca234be123f913a2a31302b7eb6"
integrity sha512-B1eufjs/mGzHqoGeI1VT/dnSBoZr2v3i3/Wm8NmdxlZflyVdleE8wO0QwUuj4NfundD7T5nU3I7HSKp/5BD9og==
typescript-memoize@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/typescript-memoize/-/typescript-memoize-1.1.0.tgz#4a8f512d06fc995167c703a3592219901db8bc79"
integrity sha512-LQPKVXK8QrBBkL/zclE6YgSWn0I8ew5m0Lf+XL00IwMhlotqRLlzHV+BRrljVQIc+NohUAuQP7mg4HQwrx5Xbg==
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
@ -13637,6 +13916,16 @@ unbox-primitive@^1.0.0:
has-symbols "^1.0.0"
which-boxed-primitive "^1.0.1"
unbox-primitive@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==
dependencies:
function-bind "^1.1.1"
has-bigints "^1.0.1"
has-symbols "^1.0.2"
which-boxed-primitive "^1.0.2"
underscore.string@^3.2.2, underscore.string@~3.3.4:
version "3.3.5"
resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.5.tgz#fc2ad255b8bd309e239cbc5816fd23a9b7ea4023"
@ -14225,7 +14514,7 @@ whatwg-url@^8.0.0:
tr46 "^2.0.2"
webidl-conversions "^6.1.0"
which-boxed-primitive@^1.0.1:
which-boxed-primitive@^1.0.1, which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==