ember-primitives 0.61.1 → 0.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/declarations/components/accordion/content.d.ts +2 -1
- package/declarations/components/accordion/content.d.ts.map +1 -1
- package/declarations/components/accordion/header.d.ts +2 -1
- package/declarations/components/accordion/header.d.ts.map +1 -1
- package/declarations/components/accordion/item.d.ts +7 -0
- package/declarations/components/accordion/item.d.ts.map +1 -1
- package/declarations/components/accordion/public.d.ts +3 -3
- package/declarations/components/accordion/public.d.ts.map +1 -1
- package/declarations/components/accordion/trigger.d.ts +2 -1
- package/declarations/components/accordion/trigger.d.ts.map +1 -1
- package/declarations/components/command-palette.d.ts +329 -0
- package/declarations/components/command-palette.d.ts.map +1 -0
- package/declarations/components/dialog.d.ts +65 -7
- package/declarations/components/dialog.d.ts.map +1 -1
- package/declarations/components/drawer.d.ts +14 -6
- package/declarations/components/drawer.d.ts.map +1 -1
- package/declarations/components/link.d.ts.map +1 -1
- package/declarations/components/menu.d.ts.map +1 -1
- package/declarations/components/one-time-password/otp.d.ts +1 -1
- package/declarations/components/one-time-password/utils.d.ts.map +1 -1
- package/declarations/components/rating/range.d.ts +1 -0
- package/declarations/components/rating/range.d.ts.map +1 -1
- package/declarations/components/rating/rating.d.ts +1 -1
- package/declarations/components/rating/rating.d.ts.map +1 -1
- package/declarations/components/rating/stars.d.ts.map +1 -1
- package/declarations/components/rating/state.d.ts +1 -0
- package/declarations/components/rating/state.d.ts.map +1 -1
- package/declarations/components/slider.d.ts +2 -0
- package/declarations/components/slider.d.ts.map +1 -1
- package/declarations/components/switch.d.ts +5 -1
- package/declarations/components/switch.d.ts.map +1 -1
- package/declarations/components/tabs.d.ts +30 -1
- package/declarations/components/tabs.d.ts.map +1 -1
- package/declarations/components/zoetrope/index.d.ts.map +1 -1
- package/declarations/index.d.ts +2 -1
- package/declarations/index.d.ts.map +1 -1
- package/dist/components/accordion.js +12 -4
- package/dist/components/accordion.js.map +1 -1
- package/dist/components/command-palette.js +370 -0
- package/dist/components/command-palette.js.map +1 -0
- package/dist/components/dialog.js +59 -3
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/drawer.js +9 -2
- package/dist/components/drawer.js.map +1 -1
- package/dist/components/link.js +1 -1
- package/dist/components/link.js.map +1 -1
- package/dist/components/menu.js +5 -1
- package/dist/components/menu.js.map +1 -1
- package/dist/components/one-time-password.js +1 -1
- package/dist/components/rating.js +1 -1
- package/dist/components/slider.js +6 -1
- package/dist/components/switch.js +1 -1
- package/dist/components/switch.js.map +1 -1
- package/dist/components/tabs.js +18 -5
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/zoetrope/styles.css +6 -1
- package/dist/components/zoetrope.js +1 -1
- package/dist/{index-gRO4Cvlf.js → index-B-yrfUe9.js} +10 -3
- package/dist/index-B-yrfUe9.js.map +1 -0
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/{otp-H5a4B4yu.js → otp-C8c1EIw6.js} +27 -15
- package/dist/otp-C8c1EIw6.js.map +1 -0
- package/dist/{rating-BrIiwDLw.js → rating-CKWhrr-L.js} +9 -5
- package/dist/rating-CKWhrr-L.js.map +1 -0
- package/package.json +2 -1
- package/src/components/accordion/content.gts +4 -2
- package/src/components/accordion/header.gts +8 -2
- package/src/components/accordion/item.gts +18 -2
- package/src/components/accordion/public.ts +12 -3
- package/src/components/accordion/trigger.gts +5 -3
- package/src/components/command-palette.gts +741 -0
- package/src/components/dialog.gts +86 -4
- package/src/components/drawer.gts +15 -3
- package/src/components/link.gts +1 -0
- package/src/components/menu.gts +7 -0
- package/src/components/one-time-password/input.gts +1 -1
- package/src/components/one-time-password/otp.gts +1 -1
- package/src/components/one-time-password/utils.ts +26 -13
- package/src/components/rating/range.gts +3 -0
- package/src/components/rating/rating.gts +7 -2
- package/src/components/rating/stars.gts +0 -1
- package/src/components/rating/state.gts +9 -0
- package/src/components/slider.gts +8 -0
- package/src/components/switch.gts +5 -2
- package/src/components/tabs.gts +35 -4
- package/src/components/zoetrope/index.gts +12 -3
- package/src/components/zoetrope/styles.css +6 -1
- package/src/index.ts +2 -1
- package/dist/index-gRO4Cvlf.js.map +0 -1
- package/dist/otp-H5a4B4yu.js.map +0 -1
- package/dist/rating-BrIiwDLw.js.map +0 -1
|
@@ -34,12 +34,22 @@ function handlePaste(event) {
|
|
|
34
34
|
// we want to split the pasted value across
|
|
35
35
|
// multiple text fields
|
|
36
36
|
event.preventDefault();
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
fillFrom(target, clipboardData.getData('Text'));
|
|
38
|
+
|
|
39
|
+
// Selected again, so that another paste gives the same result.
|
|
40
|
+
target.select();
|
|
41
|
+
|
|
42
|
+
// A cancelled paste fires no input event, and @onChange listens for that event.
|
|
43
|
+
target.dispatchEvent(new InputEvent('input', {
|
|
44
|
+
bubbles: true,
|
|
45
|
+
inputType: 'insertFromPaste'
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
function fillFrom(target, code) {
|
|
39
49
|
let i = 0;
|
|
40
50
|
let currElement = target;
|
|
41
51
|
while (currElement) {
|
|
42
|
-
currElement.value =
|
|
52
|
+
currElement.value = code[i++] || '';
|
|
43
53
|
const next = nextInput(currElement);
|
|
44
54
|
if (next instanceof HTMLInputElement) {
|
|
45
55
|
currElement = next;
|
|
@@ -47,11 +57,6 @@ function handlePaste(event) {
|
|
|
47
57
|
break;
|
|
48
58
|
}
|
|
49
59
|
}
|
|
50
|
-
|
|
51
|
-
// We want to select the first field again
|
|
52
|
-
// so that if someone holds paste, or
|
|
53
|
-
// pastes again, they get the same result.
|
|
54
|
-
target.select();
|
|
55
60
|
}
|
|
56
61
|
function handleNavigation(event) {
|
|
57
62
|
switch (event.key) {
|
|
@@ -111,14 +116,21 @@ function previousInput(current) {
|
|
|
111
116
|
}
|
|
112
117
|
const autoAdvance = event => {
|
|
113
118
|
assert('[BUG]: autoAdvance called on non-input element', event.target instanceof HTMLInputElement);
|
|
119
|
+
if ('inputType' in event && event.inputType === 'insertFromPaste') return;
|
|
114
120
|
const value = event.target.value;
|
|
115
121
|
if (value.length === 0) return;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
const data = 'data' in event && typeof event.data === 'string' ? event.data : '';
|
|
123
|
+
|
|
124
|
+
// Browser autofill puts the whole code in to the first field.
|
|
125
|
+
if (data.length > 1 || !data && value.length > 1) {
|
|
126
|
+
fillFrom(event.target, data || value);
|
|
127
|
+
event.target.select();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (data) {
|
|
131
|
+
event.target.value = data;
|
|
121
132
|
}
|
|
133
|
+
return focusRight(event);
|
|
122
134
|
};
|
|
123
135
|
function getCollectiveValue(elementTarget, length) {
|
|
124
136
|
if (!elementTarget) return;
|
|
@@ -155,7 +167,7 @@ function labelFor(inputIndex, labelFn) {
|
|
|
155
167
|
return `Please enter OTP character ${inputIndex + 1}`;
|
|
156
168
|
}
|
|
157
169
|
const waiter$1 = buildWaiter("ember-primitives:OTPInput:handleChange");
|
|
158
|
-
const Fields = setComponentTemplate(precompileTemplate("{{#each @fields as |_field i|}}\n <label>\n <span class=\"ember-primitives__sr-only\">{{labelFor i @labelFn}}</span>\n <input name=\"code{{i}}\" type=\"text\" inputmode=\"numeric\" autocomplete=\"
|
|
170
|
+
const Fields = setComponentTemplate(precompileTemplate("{{#each @fields as |_field i|}}\n <label>\n <span class=\"ember-primitives__sr-only\">{{labelFor i @labelFn}}</span>\n <input name=\"code{{i}}\" type=\"text\" inputmode=\"numeric\" autocomplete=\"one-time-code\" ...attributes {{on \"click\" selectAll}} {{on \"paste\" handlePaste}} {{on \"input\" autoAdvance}} {{on \"input\" @handleChange}} {{on \"keydown\" handleNavigation}} />\n </label>\n{{/each}}", {
|
|
159
171
|
strictMode: true,
|
|
160
172
|
scope: () => ({
|
|
161
173
|
labelFor,
|
|
@@ -287,4 +299,4 @@ const OTP = setComponentTemplate(precompileTemplate("<form {{on \"submit\" (fn h
|
|
|
287
299
|
}), templateOnly());
|
|
288
300
|
|
|
289
301
|
export { OTP as O, OTPInput as a };
|
|
290
|
-
//# sourceMappingURL=otp-
|
|
302
|
+
//# sourceMappingURL=otp-C8c1EIw6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otp-C8c1EIw6.js","sources":["../src/components/one-time-password/utils.ts","../src/components/one-time-password/input.gts","../src/components/one-time-password/buttons.gts","../src/components/one-time-password/otp.gts"],"sourcesContent":["import { assert } from '@ember/debug';\n\nfunction getInputs(current: HTMLInputElement) {\n const fieldset = current.closest('fieldset');\n\n assert('[BUG]: fieldset went missing', fieldset);\n\n return [...fieldset.querySelectorAll('input')];\n}\n\nfunction nextInput(current: HTMLInputElement) {\n const inputs = getInputs(current);\n const currentIndex = inputs.indexOf(current);\n\n return inputs[currentIndex + 1];\n}\n\nexport function selectAll(event: Event) {\n const target = event.target;\n\n assert(`selectAll is only meant for use with input elements`, target instanceof HTMLInputElement);\n\n target.select();\n}\n\nexport function handlePaste(event: Event) {\n const target = event.target;\n\n assert(\n `handlePaste is only meant for use with input elements`,\n target instanceof HTMLInputElement\n );\n\n const clipboardData = (event as ClipboardEvent).clipboardData;\n\n assert(\n `Could not get clipboardData while handling the paste event on OTP. Please report this issue on the ember-primitives repo with a reproduction. Thanks!`,\n clipboardData\n );\n\n // This is typically not good to prevent paste.\n // But because of the UX we're implementing,\n // we want to split the pasted value across\n // multiple text fields\n event.preventDefault();\n\n fillFrom(target, clipboardData.getData('Text'));\n\n // Selected again, so that another paste gives the same result.\n target.select();\n\n // A cancelled paste fires no input event, and @onChange listens for that event.\n target.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertFromPaste' }));\n}\n\nfunction fillFrom(target: HTMLInputElement, code: string) {\n let i = 0;\n let currElement: HTMLInputElement | null = target;\n\n while (currElement) {\n currElement.value = code[i++] || '';\n\n const next = nextInput(currElement);\n\n if (next instanceof HTMLInputElement) {\n currElement = next;\n } else {\n break;\n }\n }\n}\n\nexport function handleNavigation(event: KeyboardEvent) {\n switch (event.key) {\n case 'Backspace':\n return handleBackspace(event);\n case 'ArrowLeft':\n return focusLeft(event);\n case 'ArrowRight':\n return focusRight(event);\n }\n}\n\nfunction focusLeft(event: Pick<Event, 'target'>) {\n const target = event.target;\n\n assert(`only allowed on input elements`, target instanceof HTMLInputElement);\n\n const input = previousInput(target);\n\n input?.focus();\n requestAnimationFrame(() => {\n input?.select();\n });\n}\n\nfunction focusRight(event: Pick<Event, 'target'>) {\n const target = event.target;\n\n assert(`only allowed on input elements`, target instanceof HTMLInputElement);\n\n const input = nextInput(target);\n\n input?.focus();\n requestAnimationFrame(() => {\n input?.select();\n });\n}\n\nconst syntheticEvent = new InputEvent('input');\n\nfunction handleBackspace(event: KeyboardEvent) {\n if (event.key !== 'Backspace') return;\n\n /**\n * We have to prevent default because we\n * - want to clear the whole field\n * - have the focus behavior keep up with the key-repeat\n * speed of the user's computer\n */\n event.preventDefault();\n\n const target = event.target;\n\n if (target && 'value' in target) {\n if (target.value === '') {\n focusLeft({ target });\n } else {\n target.value = '';\n }\n }\n\n target?.dispatchEvent(syntheticEvent);\n}\n\nfunction previousInput(current: HTMLInputElement) {\n const inputs = getInputs(current);\n const currentIndex = inputs.indexOf(current);\n\n return inputs[currentIndex - 1];\n}\n\nexport const autoAdvance = (event: Event) => {\n assert(\n '[BUG]: autoAdvance called on non-input element',\n event.target instanceof HTMLInputElement\n );\n\n if ('inputType' in event && event.inputType === 'insertFromPaste') return;\n\n const value = event.target.value;\n\n if (value.length === 0) return;\n\n const data = 'data' in event && typeof event.data === 'string' ? event.data : '';\n\n // Browser autofill puts the whole code in to the first field.\n if (data.length > 1 || (!data && value.length > 1)) {\n fillFrom(event.target, data || value);\n event.target.select();\n\n return;\n }\n\n if (data) {\n event.target.value = data;\n }\n\n return focusRight(event);\n};\n\nexport function getCollectiveValue(elementTarget: EventTarget | null, length: number) {\n if (!elementTarget) return;\n\n assert(\n `[BUG]: somehow the element target is not HTMLElement`,\n elementTarget instanceof HTMLElement\n );\n\n let parent: null | HTMLElement | ShadowRoot;\n\n // TODO: should this logic be extracted?\n // why is getting the target element within a shadow root hard?\n if (!(elementTarget instanceof HTMLInputElement)) {\n if (elementTarget.shadowRoot) {\n parent = elementTarget.shadowRoot;\n } else {\n parent = elementTarget.closest('fieldset');\n }\n } else {\n parent = elementTarget.closest('fieldset');\n }\n\n assert(`[BUG]: somehow the input fields were rendered without a parent element`, parent);\n\n const elements = parent.querySelectorAll('input');\n\n let value = '';\n\n assert(\n `found elements (${elements.length}) do not match length (${length}). Was the same OTP input rendered more than once?`,\n elements.length === length\n );\n\n for (const element of elements) {\n assert(\n '[BUG]: how did the queried elements become a non-input element?',\n element instanceof HTMLInputElement\n );\n value += element.value;\n }\n\n return value;\n}\n","import Component from \"@glimmer/component\";\nimport { warn } from \"@ember/debug\";\nimport { isDestroyed, isDestroying } from \"@ember/destroyable\";\nimport { on } from \"@ember/modifier\";\nimport { buildWaiter } from \"@ember/test-waiters\";\n\nimport {\n autoAdvance,\n getCollectiveValue,\n handleNavigation,\n handlePaste,\n selectAll,\n} from \"./utils.ts\";\n\nimport type { TOC } from \"@ember/component/template-only\";\nimport type { WithBoundArgs } from \"@glint/template\";\n\nconst DEFAULT_LENGTH = 6;\n\nfunction labelFor(inputIndex: number, labelFn: undefined | ((index: number) => string)) {\n if (labelFn) {\n return labelFn(inputIndex);\n }\n\n return `Please enter OTP character ${inputIndex + 1}`;\n}\n\nconst waiter = buildWaiter(\"ember-primitives:OTPInput:handleChange\");\n\nconst Fields: TOC<{\n /**\n * Any attributes passed to this component will be applied to each input.\n */\n Element: HTMLInputElement;\n Args: {\n fields: unknown[];\n labelFn: (index: number) => string;\n handleChange: (event: Event) => void;\n };\n}> = <template>\n {{#each @fields as |_field i|}}\n <label>\n <span class=\"ember-primitives__sr-only\">{{labelFor i @labelFn}}</span>\n <input\n name=\"code{{i}}\"\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n ...attributes\n {{on \"click\" selectAll}}\n {{on \"paste\" handlePaste}}\n {{on \"input\" autoAdvance}}\n {{on \"input\" @handleChange}}\n {{on \"keydown\" handleNavigation}}\n />\n </label>\n {{/each}}\n</template>;\n\nexport class OTPInput extends Component<{\n /**\n * The collection of individual OTP inputs are contained by a fieldset.\n * Applying the `disabled` attribute to this fieldset will disable\n * all of the inputs, if that's desired.\n */\n Element: HTMLFieldSetElement;\n Args: {\n /**\n * How many characters the one-time-password field should be\n * Defaults to 6\n */\n length?: number;\n\n /**\n * To Customize the label of the input fields, you may pass a function.\n * By default, this is `Please enter OTP character ${index + 1}`.\n */\n labelFn?: (index: number) => string;\n\n /**\n * If passed, this function will be called when the <Input> changes.\n * All fields are considered one input.\n */\n onChange?: (\n data: {\n /**\n * The text from the collective `<Input>`\n *\n * `code` _may_ be shorter than `length`\n * if the user has not finished typing / pasting their code\n */\n code: string;\n /**\n * will be `true` if `code`'s length matches the passed `@length` or the default of 6\n */\n complete: boolean;\n },\n /**\n * The last input event received\n */\n event: Event,\n ) => void;\n };\n Blocks: {\n /**\n * Optionally, you may control how the Fields are rendered, with proceeding text,\n * additional attributes added, etc.\n *\n * This is how you can add custom validation to each input field.\n */\n default?: [fields: WithBoundArgs<typeof Fields, \"fields\" | \"handleChange\" | \"labelFn\">];\n };\n}> {\n /**\n * This is debounced, because we bind to each input,\n * but only want to emit one change event if someone pastes\n * multiple characters\n */\n handleChange = (event: Event) => {\n if (!this.args.onChange) return;\n\n if (!this.#token) {\n this.#token = waiter.beginAsync();\n }\n\n if (this.#frame) {\n cancelAnimationFrame(this.#frame);\n }\n\n // We use requestAnimationFrame to be friendly to rendering.\n // We don't know if onChange is going to want to cause paints\n // (it's also how we debounce, under the assumption that \"paste\" behavior\n // would be fast enough to be quicker than individual frames\n // (see logic in autoAdvance)\n // )\n this.#frame = requestAnimationFrame(() => {\n waiter.endAsync(this.#token);\n\n if (isDestroyed(this) || isDestroying(this)) return;\n if (!this.args.onChange) return;\n\n const value = getCollectiveValue(event.target, this.length);\n\n if (value === undefined) {\n warn(`Value could not be determined for the OTP field. was it removed from the DOM?`, {\n id: \"ember-primitives.OTPInput.missing-value\",\n });\n\n return;\n }\n\n this.args.onChange({ code: value, complete: value.length === this.length }, event);\n });\n };\n\n #token: unknown;\n #frame: number | undefined;\n\n get length() {\n return this.args.length ?? DEFAULT_LENGTH;\n }\n\n get fields() {\n // We only need to iterate a number of times,\n // so we don't care about the actual value or\n // referential integrity here\n return new Array<undefined>(this.length);\n }\n\n <template>\n <fieldset ...attributes>\n {{#let\n (component Fields fields=this.fields handleChange=this.handleChange labelFn=@labelFn)\n as |CurriedFields|\n }}\n {{#if (has-block)}}\n {{yield CurriedFields}}\n {{else}}\n <CurriedFields />\n {{/if}}\n {{/let}}\n\n <style>\n .ember-primitives__sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n }\n </style>\n </fieldset>\n </template>\n}\n","import { assert } from \"@ember/debug\";\nimport { on } from \"@ember/modifier\";\n\nimport type { TOC } from \"@ember/component/template-only\";\n\nconst reset = (event: Event) => {\n assert(\"[BUG]: reset called without an event.target\", event.target instanceof HTMLElement);\n\n const form = event.target.closest(\"form\");\n\n assert(\n \"Form is missing. Cannot use <Reset> without being contained within a <form>\",\n form instanceof HTMLFormElement,\n );\n\n form.reset();\n};\n\nexport const Submit: TOC<{\n Element: HTMLButtonElement;\n Blocks: { default: [] };\n}> = <template>\n <button type=\"submit\" ...attributes>Submit</button>\n</template>;\n\nexport const Reset: TOC<{\n Element: HTMLButtonElement;\n Blocks: { default: [] };\n}> = <template>\n <button type=\"button\" {{on \"click\" reset}} ...attributes>{{yield}}</button>\n</template>;\n","import { assert } from \"@ember/debug\";\nimport { fn, hash } from \"@ember/helper\";\nimport { on } from \"@ember/modifier\";\nimport { buildWaiter } from \"@ember/test-waiters\";\n\nimport { Reset, Submit } from \"./buttons.gts\";\nimport { OTPInput } from \"./input.gts\";\n\nimport type { TOC } from \"@ember/component/template-only\";\nimport type { WithBoundArgs } from \"@glint/template\";\n\nconst waiter = buildWaiter(\"ember-primitives:OTP:handleAutoSubmitAttempt\");\n\nconst handleFormSubmit = (submit: (data: { code: string }) => void, event: SubmitEvent) => {\n event.preventDefault();\n\n assert(\n \"[BUG]: handleFormSubmit was not attached to a form. Please open an issue.\",\n event.currentTarget instanceof HTMLFormElement,\n );\n\n const formData = new FormData(event.currentTarget);\n\n let code = \"\";\n\n for (const [key, value] of formData.entries()) {\n if (key.startsWith(\"code\")) {\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands, @typescript-eslint/no-base-to-string\n code += value;\n }\n }\n\n submit({\n code,\n });\n};\n\nfunction handleChange(\n autoSubmit: boolean | undefined,\n data: { code: string; complete: boolean },\n event: Event,\n) {\n if (!autoSubmit) return;\n if (!data.complete) return;\n\n assert(\n \"[BUG]: event target is not a known element type\",\n event.target instanceof HTMLElement || event.target instanceof SVGElement,\n );\n\n const form = event.target.closest(\"form\");\n\n assert(\"[BUG]: Cannot handle event when <OTP> Inputs are not rendered within their <form>\", form);\n\n const token = waiter.beginAsync();\n const finished = () => {\n waiter.endAsync(token);\n form.removeEventListener(\"submit\", finished);\n };\n\n form.addEventListener(\"submit\", finished);\n\n // NOTE: when calling .submit() the submit event handlers are not run\n form.requestSubmit();\n}\n\nexport const OTP: TOC<{\n /**\n * The overall OTP Input is in its own form.\n * Modern UI/UX Patterns usually have this sort of field\n * as its own page, thus within its own form.\n *\n * By default, only the 'submit' event is bound, and is\n * what calls the `@onSubmit` argument.\n */\n Element: HTMLFormElement;\n Args: {\n /**\n * How many characters the one-time-password field should be\n * Defaults to 6\n */\n length?: number;\n\n /**\n * The on submit callback will give you the entered\n * one-time-password code.\n *\n * It will be called when the user manually clicks the 'submit'\n * button or when the full code is pasted and meats the validation\n * criteria.\n */\n onSubmit: (data: { code: string }) => void;\n\n /**\n * Whether or not to auto-submit after the code has been pasted\n * in to the collective \"field\". Default is false\n */\n autoSubmit?: boolean;\n };\n Blocks: {\n default: [\n {\n /**\n * The collective input field that the OTP code will be typed/pasted in to\n */\n Input: WithBoundArgs<typeof OTPInput, \"length\" | \"onChange\">;\n /**\n * Button with `type=\"submit\"` to submit the form\n */\n Submit: typeof Submit;\n /**\n * Pre-wired button to reset the form\n */\n Reset: typeof Reset;\n },\n ];\n };\n}> = <template>\n <form {{on \"submit\" (fn handleFormSubmit @onSubmit)}} ...attributes>\n {{yield\n (hash\n Input=(component\n OTPInput length=@length onChange=(if @autoSubmit (fn handleChange @autoSubmit))\n )\n Submit=Submit\n Reset=Reset\n )\n }}\n </form>\n</template>;\n"],"names":["getInputs","current","fieldset","closest","assert","querySelectorAll","nextInput","inputs","currentIndex","indexOf","selectAll","event","target","HTMLInputElement","select","handlePaste","clipboardData","preventDefault","fillFrom","getData","dispatchEvent","InputEvent","bubbles","inputType","code","i","currElement","value","next","handleNavigation","key","handleBackspace","focusLeft","focusRight","input","previousInput","focus","requestAnimationFrame","syntheticEvent","autoAdvance","length","data","getCollectiveValue","elementTarget","HTMLElement","parent","shadowRoot","elements","element","DEFAULT_LENGTH","labelFor","inputIndex","labelFn","waiter","buildWaiter","Fields","setComponentTemplate","precompileTemplate","strictMode","scope","on","templateOnly","OTPInput","Component","handleChange","args","onChange","beginAsync","cancelAnimationFrame","endAsync","isDestroyed","isDestroying","undefined","warn","id","complete","fields","Array","reset","form","HTMLFormElement","Submit","Reset","handleFormSubmit","submit","currentTarget","formData","FormData","entries","startsWith","autoSubmit","SVGElement","token","finished","removeEventListener","addEventListener","requestSubmit","OTP","fn","hash"],"mappings":";;;;;;;;;;AAEA,SAASA,SAASA,CAACC,OAAyB,EAAE;AAC5C,EAAA,MAAMC,QAAQ,GAAGD,OAAO,CAACE,OAAO,CAAC,UAAU,CAAC;AAE5CC,EAAAA,MAAM,CAAC,8BAA8B,EAAEF,QAAQ,CAAC;EAEhD,OAAO,CAAC,GAAGA,QAAQ,CAACG,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAChD;AAEA,SAASC,SAASA,CAACL,OAAyB,EAAE;AAC5C,EAAA,MAAMM,MAAM,GAAGP,SAAS,CAACC,OAAO,CAAC;AACjC,EAAA,MAAMO,YAAY,GAAGD,MAAM,CAACE,OAAO,CAACR,OAAO,CAAC;AAE5C,EAAA,OAAOM,MAAM,CAACC,YAAY,GAAG,CAAC,CAAC;AACjC;AAEO,SAASE,SAASA,CAACC,KAAY,EAAE;AACtC,EAAA,MAAMC,MAAM,GAAGD,KAAK,CAACC,MAAM;AAE3BR,EAAAA,MAAM,CAAC,CAAA,mDAAA,CAAqD,EAAEQ,MAAM,YAAYC,gBAAgB,CAAC;EAEjGD,MAAM,CAACE,MAAM,EAAE;AACjB;AAEO,SAASC,WAAWA,CAACJ,KAAY,EAAE;AACxC,EAAA,MAAMC,MAAM,GAAGD,KAAK,CAACC,MAAM;AAE3BR,EAAAA,MAAM,CACJ,CAAA,qDAAA,CAAuD,EACvDQ,MAAM,YAAYC,gBACpB,CAAC;AAED,EAAA,MAAMG,aAAa,GAAIL,KAAK,CAAoBK,aAAa;AAE7DZ,EAAAA,MAAM,CACJ,CAAA,qJAAA,CAAuJ,EACvJY,aACF,CAAC;;AAED;AACA;AACA;AACA;EACAL,KAAK,CAACM,cAAc,EAAE;EAEtBC,QAAQ,CAACN,MAAM,EAAEI,aAAa,CAACG,OAAO,CAAC,MAAM,CAAC,CAAC;;AAE/C;EACAP,MAAM,CAACE,MAAM,EAAE;;AAEf;AACAF,EAAAA,MAAM,CAACQ,aAAa,CAAC,IAAIC,UAAU,CAAC,OAAO,EAAE;AAAEC,IAAAA,OAAO,EAAE,IAAI;AAAEC,IAAAA,SAAS,EAAE;AAAkB,GAAC,CAAC,CAAC;AAChG;AAEA,SAASL,QAAQA,CAACN,MAAwB,EAAEY,IAAY,EAAE;EACxD,IAAIC,CAAC,GAAG,CAAC;EACT,IAAIC,WAAoC,GAAGd,MAAM;AAEjD,EAAA,OAAOc,WAAW,EAAE;IAClBA,WAAW,CAACC,KAAK,GAAGH,IAAI,CAACC,CAAC,EAAE,CAAC,IAAI,EAAE;AAEnC,IAAA,MAAMG,IAAI,GAAGtB,SAAS,CAACoB,WAAW,CAAC;IAEnC,IAAIE,IAAI,YAAYf,gBAAgB,EAAE;AACpCa,MAAAA,WAAW,GAAGE,IAAI;AACpB,IAAA,CAAC,MAAM;AACL,MAAA;AACF,IAAA;AACF,EAAA;AACF;AAEO,SAASC,gBAAgBA,CAAClB,KAAoB,EAAE;EACrD,QAAQA,KAAK,CAACmB,GAAG;AACf,IAAA,KAAK,WAAW;MACd,OAAOC,eAAe,CAACpB,KAAK,CAAC;AAC/B,IAAA,KAAK,WAAW;MACd,OAAOqB,SAAS,CAACrB,KAAK,CAAC;AACzB,IAAA,KAAK,YAAY;MACf,OAAOsB,UAAU,CAACtB,KAAK,CAAC;AAC5B;AACF;AAEA,SAASqB,SAASA,CAACrB,KAA4B,EAAE;AAC/C,EAAA,MAAMC,MAAM,GAAGD,KAAK,CAACC,MAAM;AAE3BR,EAAAA,MAAM,CAAC,CAAA,8BAAA,CAAgC,EAAEQ,MAAM,YAAYC,gBAAgB,CAAC;AAE5E,EAAA,MAAMqB,KAAK,GAAGC,aAAa,CAACvB,MAAM,CAAC;EAEnCsB,KAAK,EAAEE,KAAK,EAAE;AACdC,EAAAA,qBAAqB,CAAC,MAAM;IAC1BH,KAAK,EAAEpB,MAAM,EAAE;AACjB,EAAA,CAAC,CAAC;AACJ;AAEA,SAASmB,UAAUA,CAACtB,KAA4B,EAAE;AAChD,EAAA,MAAMC,MAAM,GAAGD,KAAK,CAACC,MAAM;AAE3BR,EAAAA,MAAM,CAAC,CAAA,8BAAA,CAAgC,EAAEQ,MAAM,YAAYC,gBAAgB,CAAC;AAE5E,EAAA,MAAMqB,KAAK,GAAG5B,SAAS,CAACM,MAAM,CAAC;EAE/BsB,KAAK,EAAEE,KAAK,EAAE;AACdC,EAAAA,qBAAqB,CAAC,MAAM;IAC1BH,KAAK,EAAEpB,MAAM,EAAE;AACjB,EAAA,CAAC,CAAC;AACJ;AAEA,MAAMwB,cAAc,GAAG,IAAIjB,UAAU,CAAC,OAAO,CAAC;AAE9C,SAASU,eAAeA,CAACpB,KAAoB,EAAE;AAC7C,EAAA,IAAIA,KAAK,CAACmB,GAAG,KAAK,WAAW,EAAE;;AAE/B;AACF;AACA;AACA;AACA;AACA;EACEnB,KAAK,CAACM,cAAc,EAAE;AAEtB,EAAA,MAAML,MAAM,GAAGD,KAAK,CAACC,MAAM;AAE3B,EAAA,IAAIA,MAAM,IAAI,OAAO,IAAIA,MAAM,EAAE;AAC/B,IAAA,IAAIA,MAAM,CAACe,KAAK,KAAK,EAAE,EAAE;AACvBK,MAAAA,SAAS,CAAC;AAAEpB,QAAAA;AAAO,OAAC,CAAC;AACvB,IAAA,CAAC,MAAM;MACLA,MAAM,CAACe,KAAK,GAAG,EAAE;AACnB,IAAA;AACF,EAAA;AAEAf,EAAAA,MAAM,EAAEQ,aAAa,CAACkB,cAAc,CAAC;AACvC;AAEA,SAASH,aAAaA,CAAClC,OAAyB,EAAE;AAChD,EAAA,MAAMM,MAAM,GAAGP,SAAS,CAACC,OAAO,CAAC;AACjC,EAAA,MAAMO,YAAY,GAAGD,MAAM,CAACE,OAAO,CAACR,OAAO,CAAC;AAE5C,EAAA,OAAOM,MAAM,CAACC,YAAY,GAAG,CAAC,CAAC;AACjC;AAEO,MAAM+B,WAAW,GAAI5B,KAAY,IAAK;EAC3CP,MAAM,CACJ,gDAAgD,EAChDO,KAAK,CAACC,MAAM,YAAYC,gBAC1B,CAAC;EAED,IAAI,WAAW,IAAIF,KAAK,IAAIA,KAAK,CAACY,SAAS,KAAK,iBAAiB,EAAE;AAEnE,EAAA,MAAMI,KAAK,GAAGhB,KAAK,CAACC,MAAM,CAACe,KAAK;AAEhC,EAAA,IAAIA,KAAK,CAACa,MAAM,KAAK,CAAC,EAAE;AAExB,EAAA,MAAMC,IAAI,GAAG,MAAM,IAAI9B,KAAK,IAAI,OAAOA,KAAK,CAAC8B,IAAI,KAAK,QAAQ,GAAG9B,KAAK,CAAC8B,IAAI,GAAG,EAAE;;AAEhF;AACA,EAAA,IAAIA,IAAI,CAACD,MAAM,GAAG,CAAC,IAAK,CAACC,IAAI,IAAId,KAAK,CAACa,MAAM,GAAG,CAAE,EAAE;IAClDtB,QAAQ,CAACP,KAAK,CAACC,MAAM,EAAE6B,IAAI,IAAId,KAAK,CAAC;AACrChB,IAAAA,KAAK,CAACC,MAAM,CAACE,MAAM,EAAE;AAErB,IAAA;AACF,EAAA;AAEA,EAAA,IAAI2B,IAAI,EAAE;AACR9B,IAAAA,KAAK,CAACC,MAAM,CAACe,KAAK,GAAGc,IAAI;AAC3B,EAAA;EAEA,OAAOR,UAAU,CAACtB,KAAK,CAAC;AAC1B,CAAC;AAEM,SAAS+B,kBAAkBA,CAACC,aAAiC,EAAEH,MAAc,EAAE;EACpF,IAAI,CAACG,aAAa,EAAE;AAEpBvC,EAAAA,MAAM,CACJ,CAAA,oDAAA,CAAsD,EACtDuC,aAAa,YAAYC,WAC3B,CAAC;AAED,EAAA,IAAIC,MAAuC;;AAE3C;AACA;AACA,EAAA,IAAI,EAAEF,aAAa,YAAY9B,gBAAgB,CAAC,EAAE;IAChD,IAAI8B,aAAa,CAACG,UAAU,EAAE;MAC5BD,MAAM,GAAGF,aAAa,CAACG,UAAU;AACnC,IAAA,CAAC,MAAM;AACLD,MAAAA,MAAM,GAAGF,aAAa,CAACxC,OAAO,CAAC,UAAU,CAAC;AAC5C,IAAA;AACF,EAAA,CAAC,MAAM;AACL0C,IAAAA,MAAM,GAAGF,aAAa,CAACxC,OAAO,CAAC,UAAU,CAAC;AAC5C,EAAA;AAEAC,EAAAA,MAAM,CAAC,CAAA,sEAAA,CAAwE,EAAEyC,MAAM,CAAC;AAExF,EAAA,MAAME,QAAQ,GAAGF,MAAM,CAACxC,gBAAgB,CAAC,OAAO,CAAC;EAEjD,IAAIsB,KAAK,GAAG,EAAE;AAEdvB,EAAAA,MAAM,CACJ,CAAA,gBAAA,EAAmB2C,QAAQ,CAACP,MAAM,CAAA,uBAAA,EAA0BA,MAAM,CAAA,kDAAA,CAAoD,EACtHO,QAAQ,CAACP,MAAM,KAAKA,MACtB,CAAC;AAED,EAAA,KAAK,MAAMQ,OAAO,IAAID,QAAQ,EAAE;AAC9B3C,IAAAA,MAAM,CACJ,iEAAiE,EACjE4C,OAAO,YAAYnC,gBACrB,CAAC;IACDc,KAAK,IAAIqB,OAAO,CAACrB,KAAK;AACxB,EAAA;AAEA,EAAA,OAAOA,KAAK;AACd;;ACpMA,MAAMsB,cAAA,GAAiB,CAAA;AAEvB,SAASC,QAAAA,CAASC,UAAkB,EAAEC,OAAgD,EAAA;AACpF,EAAA,IAAIA,OAAA,EAAS;IACX,OAAOA,OAAA,CAAQD,UAAA,CAAA;AACjB,EAAA;AAEA,EAAA,OAAO,CAAA,2BAAA,EAA8BA,UAAA,GAAa,GAAG;AACvD;AAEA,MAAME,WAASC,WAAA,CAAY,wCAAA,CAAA;AAE3B,MAAMC,MAUD,GAAAC,oBAAA,CAAAC,kBAAA,CAAA,4ZAAA,EAkBL;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;IAAAT,QAAA;IAAAU,EAAA;IAAAlD,SAAA;IAAAK,WAAA;IAAAwB,WAAA;AAAAV,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAgC,YAAA,EAAA,CAAA;AAEH,MAAMC,QAAA,SAAiBC,SAAA;AAsD5B;;;;;EAKAC,YAAA,GAAgBrD,KAAO,IAAA;AACrB,IAAA,IAAI,CAAC,IAAI,CAACsD,IAAI,CAACC,QAAQ,EAAE;AAEzB,IAAA,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;MAChB,IAAI,CAAC,MAAM,GAAGb,SAAOc,UAAU,EAAA;AACjC,IAAA;AAEA,IAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACfC,MAAAA,oBAAA,CAAqB,IAAI,CAAC,MAAM,CAAA;AAClC,IAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA,IAAI,CAAC,MAAM,GAAG/B,qBAAA,CAAsB,MAAA;AAClCgB,MAAAA,QAAA,CAAOgB,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAA;MAE3B,IAAIC,WAAA,CAAY,IAAI,CAAA,IAAKC,YAAA,CAAa,IAAI,CAAA,EAAG;AAC7C,MAAA,IAAI,CAAC,IAAI,CAACN,IAAI,CAACC,QAAQ,EAAE;MAEzB,MAAMvC,QAAQe,kBAAA,CAAmB/B,KAAA,CAAMC,MAAM,EAAE,IAAI,CAAC4B,MAAM,CAAA;MAE1D,IAAIb,UAAU6C,SAAA,EAAW;QACvBC,IAAA,CAAK,+EAA+E,EAAE;AACpFC,UAAAA,EAAA,EAAI;AACN,SAAA,CAAA;AAEA,QAAA;AACF,MAAA;AAEA,MAAA,IAAI,CAACT,IAAI,CAACC,QAAQ,CAAC;AAAE1C,QAAAA,IAAA,EAAMG,KAAA;AAAOgD,QAAAA,QAAA,EAAUhD,KAAA,CAAMa,MAAM,KAAK,IAAI,CAACA;OAAO,EAAG7B,KAAA,CAAA;AAC9E,IAAA,CAAA,CAAA;EACF,CAAA;AAEA,EAAA,MAAM;AACN,EAAA,MAAM;EAEN,IAAI6B,MAAAA,GAAS;AACX,IAAA,OAAO,IAAI,CAACyB,IAAI,CAACzB,MAAM,IAAIS,cAAA;AAC7B,EAAA;EAEA,IAAI2B,MAAAA,GAAS;AACX;AACA;AACA;AACA,IAAA,OAAO,IAAIC,KAAA,CAAiB,IAAI,CAACrC,MAAM,CAAA;AACzC,EAAA;AAEA,EAAA;IAAAgB,oBAAA,CAAAC,kBAAA,CAAA,4iBAAA,EA2BA;MAAAC,UAAA,EAAA,IAAA;AAAAC,MAAAA,KAAA,EAAAA,OAAA;AAAAJ,QAAAA;AAAA,OAAA;KAAU,CAAA,EAAV,IAAW,CAAA;AAAD;AACZ;;AChMA,MAAMuB,KAAA,GAASnE,KAAO,IAAA;EACpBP,MAAA,CAAO,6CAAA,EAA+CO,KAAA,CAAMC,MAAM,YAAYgC,WAAA,CAAA;EAE9E,MAAMmC,IAAA,GAAOpE,KAAA,CAAMC,MAAM,CAACT,OAAO,CAAC,MAAA,CAAA;AAElCC,EAAAA,MAAA,CACE,+EACA2E,IAAA,YAAgBC,eAAA,CAAA;EAGlBD,IAAA,CAAKD,KAAK,EAAA;AACZ,CAAA;AAEO,MAAMG,8BAGRxB,kBAAA,CAAA,uDAAA,EAEL;EAAAC,UAAA,EAAA;AAAU,CAAA,CAAA,EAAAG,YAAA,EAAA,CAAA;AAEH,MAAMqB,6BAGRzB,kBAAA,CAAA,iFAAA,EAEL;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;IAAAC,EAAA;AAAAkB,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAjB,YAAA,EAAA,CAAA;;ACnBV,MAAMR,SAASC,WAAA,CAAY,8CAAA,CAAA;AAE3B,MAAM6B,gBAAA,GAAmBA,CAACC,MAAwC,EAAEzE,KAAO,KAAA;EACzEA,KAAA,CAAMM,cAAc,EAAA;EAEpBb,MAAA,CACE,2EAAA,EACAO,KAAA,CAAM0E,aAAa,YAAYL,eAAA,CAAA;EAGjC,MAAMM,QAAA,GAAW,IAAIC,QAAA,CAAS5E,KAAA,CAAM0E,aAAa,CAAA;EAEjD,IAAI7D,IAAA,GAAO,EAAA;AAEX,EAAA,KAAK,MAAM,CAACM,GAAA,EAAKH,MAAM,IAAI2D,QAAA,CAASE,OAAO,EAAA,EAAI;AAC7C,IAAA,IAAI1D,GAAA,CAAI2D,UAAU,CAAC,MAAA,CAAA,EAAS;AAC1B;AACAjE,MAAAA,IAAA,IAAQG,KAAA;AACV,IAAA;AACF,EAAA;AAEAyD,EAAAA,MAAA,CAAO;AACL5D,IAAAA;AACF,GAAA,CAAA;AACF,CAAA;AAEA,SAASwC,YAAAA,CACP0B,UAA+B,EAC/BjD,IAAyC,EACzC9B,KAAY,EAAA;EAEZ,IAAI,CAAC+E,UAAA,EAAY;AACjB,EAAA,IAAI,CAACjD,IAAA,CAAKkC,QAAQ,EAAE;AAEpBvE,EAAAA,MAAA,CACE,mDACAO,KAAA,CAAMC,MAAM,YAAYgC,WAAA,IAAejC,KAAA,CAAMC,MAAM,YAAY+E,UAAA,CAAA;EAGjE,MAAMZ,IAAA,GAAOpE,KAAA,CAAMC,MAAM,CAACT,OAAO,CAAC,MAAA,CAAA;AAElCC,EAAAA,MAAA,CAAO,mFAAA,EAAqF2E,IAAA,CAAA;AAE5F,EAAA,MAAMa,KAAA,GAAQvC,OAAOc,UAAU,EAAA;EAC/B,MAAM0B,QAAA,GAAWA,MAAA;AACfxC,IAAAA,MAAA,CAAOgB,QAAQ,CAACuB,KAAA,CAAA;AAChBb,IAAAA,IAAA,CAAKe,mBAAmB,CAAC,QAAA,EAAUD,QAAA,CAAA;EACrC,CAAA;AAEAd,EAAAA,IAAA,CAAKgB,gBAAgB,CAAC,QAAA,EAAUF,QAAA,CAAA;AAEhC;EACAd,IAAA,CAAKiB,aAAa,EAAA;AACpB;MAEaC,GAmDR,GAAAzC,oBAAA,CAAAC,kBAAA,CAAA,iOAAA,EAYL;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;IAAAC,EAAA;IAAAsC,EAAA;IAAAf,gBAAA;IAAAgB,IAAA;IAAArC,QAAA;IAAAE,YAAA;IAAAiB,MAAA;AAAAC,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAArB,YAAA,EAAA;;;;"}
|
|
@@ -10,7 +10,7 @@ import { assert } from '@ember/debug';
|
|
|
10
10
|
import { localCopy } from 'tracked-toolbox';
|
|
11
11
|
import { g, i, n } from 'decorator-transforms/runtime';
|
|
12
12
|
|
|
13
|
-
const RatingRange = setComponentTemplate(precompileTemplate("<input ...attributes name={{@name}} type=\"range\" max={{@max}} value={{@value}} {{on \"change\" @handleChange}} />", {
|
|
13
|
+
const RatingRange = setComponentTemplate(precompileTemplate("<input min=\"0\" step={{@step}} ...attributes name={{@name}} type=\"range\" max={{@max}} value={{@value}} {{on \"change\" @handleChange}} />", {
|
|
14
14
|
strictMode: true,
|
|
15
15
|
scope: () => ({
|
|
16
16
|
on
|
|
@@ -24,7 +24,7 @@ function lte(a, b) {
|
|
|
24
24
|
return a <= b;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const Stars = setComponentTemplate(precompileTemplate("<div class=\"ember-primitives__rating__items\">\n {{#each @stars as |star|}}\n {{#let (uniqueId) as |id|}}\n <span class=\"ember-primitives__rating__item\" data-number={{star}} data-selected={{lte star @currentValue}} data-readonly={{@isReadonly}}>\n <label for=\"input-{{id}}\">\n <span visually-hidden>{{star}} star</span>\n {{#if @icon}}\n <span aria-hidden=\"true\">\n {{#if (isString @icon)}}\n {{@icon}}\n {{else}}\n <@icon @value={{star}} @isSelected={{lte star @currentValue}} @readonly={{@isReadonly}} />\n {{/if}}\n </span>\n {{/if}}\n </label>\n\n <input id=\"input-{{id}}\" type=\"radio\" name={{@name}} value={{star}}
|
|
27
|
+
const Stars = setComponentTemplate(precompileTemplate("<div class=\"ember-primitives__rating__items\">\n {{#each @stars as |star|}}\n {{#let (uniqueId) as |id|}}\n <span class=\"ember-primitives__rating__item\" data-number={{star}} data-selected={{lte star @currentValue}} data-readonly={{@isReadonly}}>\n <label for=\"input-{{id}}\">\n <span visually-hidden>{{star}} star</span>\n {{#if @icon}}\n <span aria-hidden=\"true\">\n {{#if (isString @icon)}}\n {{@icon}}\n {{else}}\n <@icon @value={{star}} @isSelected={{lte star @currentValue}} @readonly={{@isReadonly}} />\n {{/if}}\n </span>\n {{/if}}\n </label>\n\n <input id=\"input-{{id}}\" type=\"radio\" name={{@name}} value={{star}} checked={{Object.is star @currentValue}} />\n </span>\n {{/let}}\n {{/each}}\n</div>", {
|
|
28
28
|
strictMode: true,
|
|
29
29
|
scope: () => ({
|
|
30
30
|
uniqueId,
|
|
@@ -94,6 +94,10 @@ class RatingState extends Component {
|
|
|
94
94
|
// we don't do anything on other elements
|
|
95
95
|
const isValid = event.target instanceof HTMLInputElement && event.target.name === this.args.name && event.target.type === "radio";
|
|
96
96
|
if (!isValid) return;
|
|
97
|
+
if (this.args.readonly) {
|
|
98
|
+
/** `readonly` has no effect on a radio, cancelling is what restores the checked one. */event.preventDefault();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
97
101
|
const selected = event.target?.value;
|
|
98
102
|
this.setFromString(selected);
|
|
99
103
|
};
|
|
@@ -107,7 +111,7 @@ class RatingState extends Component {
|
|
|
107
111
|
this.setFromString(event.target.value);
|
|
108
112
|
};
|
|
109
113
|
static {
|
|
110
|
-
setComponentTemplate(precompileTemplate("{{yield (hash stars=this.stars total=this.stars.length handleClick=this.handleClick handleChange=this.handleChange setRating=this.setRating value=this.value step=this.step) (hash total=this.stars.length value=this.value)}}", {
|
|
114
|
+
setComponentTemplate(precompileTemplate("{{yield (hash stars=this.stars max=this.max total=this.stars.length handleClick=this.handleClick handleChange=this.handleChange setRating=this.setRating value=this.value step=this.step) (hash total=this.stars.length value=this.value)}}", {
|
|
111
115
|
strictMode: true,
|
|
112
116
|
scope: () => ({
|
|
113
117
|
hash
|
|
@@ -135,7 +139,7 @@ class Rating extends Component {
|
|
|
135
139
|
return !this.isInteractive;
|
|
136
140
|
}
|
|
137
141
|
static {
|
|
138
|
-
setComponentTemplate(precompileTemplate("<RatingState @max={{@max}} @step={{@step}} @value={{@value}} @name={{this.name}} @readonly={{this.isReadonly}} @onChange={{@onChange}} as |r publicState|>\n <fieldset class=\"ember-primitives__rating\" data-total={{r.total}} data-value={{r.value}} data-readonly={{this.isReadonly}} {{!-- We use event delegation, this isn't a primary interactive -- we're capturing events from inputs --}} {{!-- template-lint-disable no-invalid-interactive --}} {{on \"click\" r.handleClick}} ...attributes>\n {{#let (component Stars stars=r.stars icon=this.icon isReadonly=this.isReadonly name=this.name total=r.total currentValue=r.value) as |RatingStars|}}\n\n {{#if (has-block)}}\n {{yield (hash max=r.total total=r.total value=r.value name=this.name isReadonly=this.isReadonly isChangeable=this.isChangeable Stars=RatingStars Range=(component RatingRange step=r.step max=r.
|
|
142
|
+
setComponentTemplate(precompileTemplate("<RatingState @max={{@max}} @step={{@step}} @value={{@value}} @name={{this.name}} @readonly={{this.isReadonly}} @onChange={{@onChange}} as |r publicState|>\n <fieldset class=\"ember-primitives__rating\" role=\"radiogroup\" aria-readonly={{if this.isReadonly \"true\"}} data-total={{r.total}} data-value={{r.value}} data-readonly={{this.isReadonly}} {{!-- We use event delegation, this isn't a primary interactive -- we're capturing events from inputs --}} {{!-- template-lint-disable no-invalid-interactive --}} {{on \"click\" r.handleClick}} ...attributes>\n {{#let (component Stars stars=r.stars icon=this.icon isReadonly=this.isReadonly name=this.name total=r.total currentValue=r.value) as |RatingStars|}}\n\n {{#if (has-block)}}\n {{yield (hash max=r.total total=r.total value=r.value name=this.name isReadonly=this.isReadonly isChangeable=this.isChangeable Stars=RatingStars Range=(component RatingRange step=r.step max=r.max value=r.value name=this.name handleChange=r.handleChange))}}\n {{else}}\n {{#if this.needsDescription}}\n {{#if (has-block \"label\")}}\n {{yield publicState to=\"label\"}}\n {{else}}\n <span visually-hidden class=\"ember-primitives__rating__label\">Rated\n {{r.value}}\n out of\n {{r.total}}</span>\n {{/if}}\n {{else}}\n {{#if (has-block \"label\")}}\n <legend>\n {{yield publicState to=\"label\"}}\n </legend>\n {{/if}}\n {{/if}}\n\n <RatingStars />\n {{/if}}\n {{/let}}\n\n </fieldset>\n</RatingState>", {
|
|
139
143
|
strictMode: true,
|
|
140
144
|
scope: () => ({
|
|
141
145
|
RatingState,
|
|
@@ -149,4 +153,4 @@ class Rating extends Component {
|
|
|
149
153
|
}
|
|
150
154
|
|
|
151
155
|
export { Rating as R };
|
|
152
|
-
//# sourceMappingURL=rating-
|
|
156
|
+
//# sourceMappingURL=rating-CKWhrr-L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rating-CKWhrr-L.js","sources":["../src/components/rating/range.gts","../src/components/rating/utils.ts","../src/components/rating/stars.gts","../src/components/rating/state.gts","../src/components/rating/rating.gts"],"sourcesContent":["import { on } from \"@ember/modifier\";\n\nimport type { TOC } from \"@ember/component/template-only\";\n\nexport const RatingRange: TOC<{\n Element: HTMLInputElement;\n Args: {\n name: string;\n step: number;\n max: number;\n value: number;\n handleChange: (event: Event) => void;\n };\n}> = <template>\n <input\n min=\"0\"\n step={{@step}}\n ...attributes\n name={{@name}}\n type=\"range\"\n max={{@max}}\n value={{@value}}\n {{on \"change\" @handleChange}}\n />\n</template>;\n","export function isString(x: unknown) {\n return typeof x === 'string';\n}\n\nexport function lte(a: number, b: number) {\n return a <= b;\n}\n","import { uniqueId } from \"../../utils.ts\";\nimport { isString, lte } from \"./utils.ts\";\n\nimport type { ComponentIcons, StringIcons } from \"./public-types.ts\";\nimport type { TOC } from \"@ember/component/template-only\";\n\nexport const Stars: TOC<{\n Args: {\n // Configuration\n stars: number[];\n icon: StringIcons[\"icon\"] | ComponentIcons[\"icon\"];\n isReadonly: boolean;\n\n // HTML Boilerplate\n name: string;\n\n // State\n currentValue: number;\n total: number;\n };\n}> = <template>\n <div class=\"ember-primitives__rating__items\">\n {{#each @stars as |star|}}\n {{#let (uniqueId) as |id|}}\n <span\n class=\"ember-primitives__rating__item\"\n data-number={{star}}\n data-selected={{lte star @currentValue}}\n data-readonly={{@isReadonly}}\n >\n <label for=\"input-{{id}}\">\n <span visually-hidden>{{star}} star</span>\n {{#if @icon}}\n <span aria-hidden=\"true\">\n {{#if (isString @icon)}}\n {{@icon}}\n {{else}}\n <@icon\n @value={{star}}\n @isSelected={{lte star @currentValue}}\n @readonly={{@isReadonly}}\n />\n {{/if}}\n </span>\n {{/if}}\n </label>\n\n <input\n id=\"input-{{id}}\"\n type=\"radio\"\n name={{@name}}\n value={{star}}\n checked={{Object.is star @currentValue}}\n />\n </span>\n {{/let}}\n {{/each}}\n </div>\n</template>;\n","import Component from \"@glimmer/component\";\nimport { cached } from \"@glimmer/tracking\";\nimport { assert } from \"@ember/debug\";\nimport { hash } from \"@ember/helper\";\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-expect-error\nimport { localCopy } from \"tracked-toolbox\";\n\nexport class RatingState extends Component<{\n Args: {\n max: number | undefined;\n value: number | undefined;\n step: number | undefined;\n readonly: boolean | undefined;\n name: string;\n onChange?: (value: number) => void;\n };\n Blocks: {\n default: [\n internalApi: {\n stars: number[];\n step: number;\n value: number;\n max: number;\n total: number;\n handleClick: (event: Event) => void;\n handleChange: (event: Event) => void;\n setRating: (num: number) => void;\n },\n publicApi: {\n value: number;\n total: number;\n },\n ];\n };\n}> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n @localCopy(\"args.value\") declare _value: number;\n\n get value() {\n return this._value ?? 0;\n }\n\n get step() {\n return this.args.step ?? 1;\n }\n\n get max() {\n return this.args.max ?? 5;\n }\n\n @cached\n get stars() {\n const result = [];\n\n // 0 is \"none selected\"\n let current = 0;\n\n current += this.step;\n\n while (current <= this.max) {\n result.push(current);\n current += this.step;\n }\n\n return result;\n }\n\n setRating = (value: number) => {\n if (this.args.readonly) {\n return;\n }\n\n if (value === this._value) {\n this._value = 0;\n } else {\n this._value = value;\n }\n\n this.args.onChange?.(value);\n };\n\n setFromString = (value: unknown) => {\n assert(\"[BUG]: value from input must be a string.\", typeof value === \"string\");\n\n const num = parseFloat(value);\n\n if (isNaN(num)) {\n // something went wrong.\n // Since we're using event delegation,\n // this could be from an unrelated input\n return;\n }\n\n this.setRating(num);\n };\n\n /**\n * Click events are captured by\n * - radio changes (mouse and keyboard)\n * - but only range clicks\n */\n handleClick = (event: Event) => {\n // Since we're doing event delegation on a click, we want to make sure\n // we don't do anything on other elements\n const isValid =\n event.target instanceof HTMLInputElement &&\n event.target.name === this.args.name &&\n event.target.type === \"radio\";\n\n if (!isValid) return;\n\n if (this.args.readonly) {\n /** `readonly` has no effect on a radio, cancelling is what restores the checked one. */\n event.preventDefault();\n\n return;\n }\n\n const selected = event.target?.value;\n\n this.setFromString(selected);\n };\n\n /**\n * Only attached to a range element, if present.\n * Range elements don't fire click events on keyboard usage, like radios do\n */\n handleChange = (event: Event) => {\n const isValid = event.target !== null && \"value\" in event.target;\n\n if (!isValid) return;\n\n this.setFromString(event.target.value);\n };\n\n <template>\n {{yield\n (hash\n stars=this.stars\n max=this.max\n total=this.stars.length\n handleClick=this.handleClick\n handleChange=this.handleChange\n setRating=this.setRating\n value=this.value\n step=this.step\n )\n (hash total=this.stars.length value=this.value)\n }}\n </template>\n}\n","import Component from \"@glimmer/component\";\nimport { hash } from \"@ember/helper\";\nimport { on } from \"@ember/modifier\";\n\nimport { uniqueId } from \"../../utils.ts\";\nimport { RatingRange } from \"./range.gts\";\nimport { Stars } from \"./stars.gts\";\nimport { RatingState } from \"./state.gts\";\n\nimport type { ComponentIcons, StringIcons } from \"./public-types.ts\";\nimport type { WithBoundArgs } from \"@glint/template\";\n\nexport interface Signature {\n /*\n * The element all passed attributes / modifiers are applied to.\n *\n * This is a `<fieldset>`, becaues the rating elements are\n * powered by a group of radio buttons.\n */\n Element: HTMLFieldSetElement;\n Args: (ComponentIcons | StringIcons) & {\n /**\n * The number of stars/whichever-icon to show\n *\n * Defaults to 5\n */\n max?: number;\n\n /**\n * The current number of stars/whichever-icon to show as selected\n *\n * Defaults to 0\n */\n value?: number;\n\n /**\n * When generating the radio inputs, this changes what value of rating each radio\n * input will be incremented by.\n *\n * e.g.: Set to 0.5 for half-star ratings.\n *\n * Defaults to 1\n */\n step?: number;\n\n /**\n * Prevents click events on the icons and sets aria-readonly.\n *\n * Also sets data-readonly=true on the wrapping element\n */\n readonly?: boolean;\n\n /**\n * Toggles the ability to interact with the rating component.\n * When `true` (the default), the Rating component can be as a form input\n * to gather user feedback.\n *\n * When false, only the `@value` will be shown, and it cannot be changed.\n */\n interactive?: boolean;\n\n /**\n * Callback when the selected rating changes.\n * Can include half-ratings if the iconHalf argument is passed.\n */\n onChange?: (value: number) => void;\n };\n\n Blocks: {\n default: [\n rating: {\n /**\n * The maximum rating\n */\n max: number;\n /**\n * The maxium rating\n */\n total: number;\n /**\n * The current rating\n */\n value: number;\n /**\n * The name shared by the field group\n */\n name: string;\n /**\n * If the rating can be changed\n */\n isReadonly: boolean;\n /**\n * If the rating can be changed\n */\n isChangeable: boolean;\n /**\n * The stars / items radio group\n */\n Stars: WithBoundArgs<\n typeof Stars,\n \"stars\" | \"icon\" | \"isReadonly\" | \"name\" | \"total\" | \"currentValue\"\n >;\n /**\n * Input range for adjusting the rating via fractional means\n */\n Range: WithBoundArgs<\n typeof RatingRange,\n \"step\" | \"max\" | \"value\" | \"name\" | \"handleChange\"\n >;\n },\n ];\n label: [\n state: {\n /**\n * The current rating\n */\n value: number;\n\n /**\n * The maximum rating\n */\n total: number;\n },\n ];\n };\n}\n\nexport class Rating extends Component<Signature> {\n name = `rating-${uniqueId()}`;\n\n get icon() {\n return this.args.icon ?? \"★\";\n }\n\n get isInteractive() {\n return this.args.interactive ?? true;\n }\n\n get isChangeable() {\n const readonly = this.args.readonly ?? false;\n\n return !readonly && this.isInteractive;\n }\n\n get isReadonly() {\n return !this.isChangeable;\n }\n\n get needsDescription() {\n return !this.isInteractive;\n }\n\n <template>\n <RatingState\n @max={{@max}}\n @step={{@step}}\n @value={{@value}}\n @name={{this.name}}\n @readonly={{this.isReadonly}}\n @onChange={{@onChange}}\n as |r publicState|\n >\n <fieldset\n class=\"ember-primitives__rating\"\n role=\"radiogroup\"\n aria-readonly={{if this.isReadonly \"true\"}}\n data-total={{r.total}}\n data-value={{r.value}}\n data-readonly={{this.isReadonly}}\n {{! We use event delegation, this isn't a primary interactive -- we're capturing events from inputs }}\n {{! template-lint-disable no-invalid-interactive }}\n {{on \"click\" r.handleClick}}\n ...attributes\n >\n {{#let\n (component\n Stars\n stars=r.stars\n icon=this.icon\n isReadonly=this.isReadonly\n name=this.name\n total=r.total\n currentValue=r.value\n )\n as |RatingStars|\n }}\n\n {{#if (has-block)}}\n {{yield\n (hash\n max=r.total\n total=r.total\n value=r.value\n name=this.name\n isReadonly=this.isReadonly\n isChangeable=this.isChangeable\n Stars=RatingStars\n Range=(component\n RatingRange\n step=r.step\n max=r.max\n value=r.value\n name=this.name\n handleChange=r.handleChange\n )\n )\n }}\n {{else}}\n {{#if this.needsDescription}}\n {{#if (has-block \"label\")}}\n {{yield publicState to=\"label\"}}\n {{else}}\n <span visually-hidden class=\"ember-primitives__rating__label\">Rated\n {{r.value}}\n out of\n {{r.total}}</span>\n {{/if}}\n {{else}}\n {{#if (has-block \"label\")}}\n <legend>\n {{yield publicState to=\"label\"}}\n </legend>\n {{/if}}\n {{/if}}\n\n <RatingStars />\n {{/if}}\n {{/let}}\n\n </fieldset>\n </RatingState>\n </template>\n}\n"],"names":["RatingRange","setComponentTemplate","precompileTemplate","strictMode","scope","on","templateOnly","isString","x","lte","a","b","Stars","uniqueId","Object","RatingState","Component","localCopy","i","value","_value","step","args","max","stars","result","current","push","n","prototype","cached","setRating","readonly","onChange","setFromString","assert","num","parseFloat","isNaN","handleClick","event","isValid","target","HTMLInputElement","name","type","preventDefault","selected","handleChange","hash","Rating","icon","isInteractive","interactive","isChangeable","isReadonly","needsDescription"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember-primitives",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.0",
|
|
4
4
|
"description": "Making apps easier to build",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -138,6 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
"scripts": {
|
|
140
140
|
"build": "rollup --config ./rollup.config.mjs",
|
|
141
|
+
"sync": "echo 'pnpm is syncing this package into the workspaces that inject it. (this is configured in .npmrc)'",
|
|
141
142
|
"lint": "concurrently 'pnpm:lint:*(!fix)' --names 'lint:'",
|
|
142
143
|
"lint:fix": "concurrently 'pnpm:lint:*:fix' --names 'fix:' && pnpm format",
|
|
143
144
|
"lint:js": "eslint . --cache",
|
|
@@ -7,7 +7,8 @@ import type { AccordionContentExternalSignature } from "./public.ts";
|
|
|
7
7
|
interface Signature extends AccordionContentExternalSignature {
|
|
8
8
|
Args: {
|
|
9
9
|
isExpanded: boolean;
|
|
10
|
-
|
|
10
|
+
triggerId: string;
|
|
11
|
+
contentId: string;
|
|
11
12
|
disabled?: boolean;
|
|
12
13
|
};
|
|
13
14
|
}
|
|
@@ -16,7 +17,8 @@ export class AccordionContent extends Component<Signature> {
|
|
|
16
17
|
<template>
|
|
17
18
|
<div
|
|
18
19
|
role="region"
|
|
19
|
-
id={{@
|
|
20
|
+
id={{@contentId}}
|
|
21
|
+
aria-labelledby={{@triggerId}}
|
|
20
22
|
data-state={{getDataState @isExpanded}}
|
|
21
23
|
hidden={{this.isHidden}}
|
|
22
24
|
data-disabled={{@disabled}}
|
|
@@ -8,7 +8,8 @@ import type { TOC } from "@ember/component/template-only";
|
|
|
8
8
|
|
|
9
9
|
interface Signature extends AccordionHeaderExternalSignature {
|
|
10
10
|
Args: {
|
|
11
|
-
|
|
11
|
+
triggerId: string;
|
|
12
|
+
contentId: string;
|
|
12
13
|
isExpanded: boolean;
|
|
13
14
|
disabled?: boolean;
|
|
14
15
|
toggleItem: () => void;
|
|
@@ -26,7 +27,12 @@ export const AccordionHeader: TOC<Signature> = <template>
|
|
|
26
27
|
{{yield
|
|
27
28
|
(hash
|
|
28
29
|
Trigger=(component
|
|
29
|
-
Trigger
|
|
30
|
+
Trigger
|
|
31
|
+
triggerId=@triggerId
|
|
32
|
+
contentId=@contentId
|
|
33
|
+
isExpanded=@isExpanded
|
|
34
|
+
disabled=@disabled
|
|
35
|
+
toggleItem=@toggleItem
|
|
30
36
|
)
|
|
31
37
|
)
|
|
32
38
|
}}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Component from "@glimmer/component";
|
|
2
2
|
import { hash } from "@ember/helper";
|
|
3
3
|
|
|
4
|
+
import { uniqueId } from "../../utils.ts";
|
|
4
5
|
import Content from "./content.gts";
|
|
5
6
|
import Header from "./header.gts";
|
|
6
7
|
|
|
@@ -19,6 +20,14 @@ interface Signature extends AccordionItemExternalSignature {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export class AccordionItem extends Component<Signature> {
|
|
23
|
+
/**
|
|
24
|
+
* `@value` only has to be unique within one accordion.
|
|
25
|
+
* Element ids have to be unique across the document.
|
|
26
|
+
*/
|
|
27
|
+
id = `ember-primitives__accordion-${uniqueId()}`;
|
|
28
|
+
triggerId = `${this.id}__trigger`;
|
|
29
|
+
contentId = `${this.id}__content`;
|
|
30
|
+
|
|
22
31
|
<template>
|
|
23
32
|
<div data-state={{getDataState this.isExpanded}} data-disabled={{@disabled}} ...attributes>
|
|
24
33
|
{{yield
|
|
@@ -26,12 +35,19 @@ export class AccordionItem extends Component<Signature> {
|
|
|
26
35
|
isExpanded=this.isExpanded
|
|
27
36
|
Header=(component
|
|
28
37
|
Header
|
|
29
|
-
|
|
38
|
+
triggerId=this.triggerId
|
|
39
|
+
contentId=this.contentId
|
|
30
40
|
isExpanded=this.isExpanded
|
|
31
41
|
disabled=@disabled
|
|
32
42
|
toggleItem=this.toggleItem
|
|
33
43
|
)
|
|
34
|
-
Content=(component
|
|
44
|
+
Content=(component
|
|
45
|
+
Content
|
|
46
|
+
triggerId=this.triggerId
|
|
47
|
+
contentId=this.contentId
|
|
48
|
+
isExpanded=this.isExpanded
|
|
49
|
+
disabled=@disabled
|
|
50
|
+
)
|
|
35
51
|
)
|
|
36
52
|
}}
|
|
37
53
|
</div>
|
|
@@ -29,7 +29,10 @@ export interface AccordionHeaderExternalSignature {
|
|
|
29
29
|
/**
|
|
30
30
|
* The AccordionTrigger component.
|
|
31
31
|
*/
|
|
32
|
-
Trigger: WithBoundArgs<
|
|
32
|
+
Trigger: WithBoundArgs<
|
|
33
|
+
typeof Trigger,
|
|
34
|
+
'triggerId' | 'contentId' | 'isExpanded' | 'disabled' | 'toggleItem'
|
|
35
|
+
>;
|
|
33
36
|
},
|
|
34
37
|
];
|
|
35
38
|
};
|
|
@@ -47,11 +50,17 @@ export interface AccordionItemExternalSignature {
|
|
|
47
50
|
/**
|
|
48
51
|
* The AccordionHeader component.
|
|
49
52
|
*/
|
|
50
|
-
Header: WithBoundArgs<
|
|
53
|
+
Header: WithBoundArgs<
|
|
54
|
+
typeof Header,
|
|
55
|
+
'triggerId' | 'contentId' | 'isExpanded' | 'disabled' | 'toggleItem'
|
|
56
|
+
>;
|
|
51
57
|
/**
|
|
52
58
|
* The AccordionContent component.
|
|
53
59
|
*/
|
|
54
|
-
Content: WithBoundArgs<
|
|
60
|
+
Content: WithBoundArgs<
|
|
61
|
+
typeof Content,
|
|
62
|
+
'triggerId' | 'contentId' | 'isExpanded' | 'disabled'
|
|
63
|
+
>;
|
|
55
64
|
},
|
|
56
65
|
];
|
|
57
66
|
};
|
|
@@ -8,7 +8,8 @@ import type { TOC } from "@ember/component/template-only";
|
|
|
8
8
|
interface Signature extends AccordionTriggerExternalSignature {
|
|
9
9
|
Args: {
|
|
10
10
|
isExpanded: boolean;
|
|
11
|
-
|
|
11
|
+
triggerId: string;
|
|
12
|
+
contentId: string;
|
|
12
13
|
disabled?: boolean;
|
|
13
14
|
toggleItem: () => void;
|
|
14
15
|
};
|
|
@@ -17,8 +18,9 @@ interface Signature extends AccordionTriggerExternalSignature {
|
|
|
17
18
|
export const AccordionTrigger: TOC<Signature> = <template>
|
|
18
19
|
<button
|
|
19
20
|
type="button"
|
|
20
|
-
|
|
21
|
-
aria-
|
|
21
|
+
id={{@triggerId}}
|
|
22
|
+
aria-controls={{@contentId}}
|
|
23
|
+
aria-expanded={{if @isExpanded "true" "false"}}
|
|
22
24
|
data-state={{getDataState @isExpanded}}
|
|
23
25
|
data-disabled={{@disabled}}
|
|
24
26
|
aria-disabled={{if @disabled "true" "false"}}
|