ember-primitives 0.44.0 → 0.45.1

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.
Files changed (97) hide show
  1. package/declarations/components/heading.d.ts.map +1 -1
  2. package/declarations/components/one-time-password.d.ts +3 -0
  3. package/declarations/components/one-time-password.d.ts.map +1 -0
  4. package/declarations/components/shadowed.d.ts +33 -3
  5. package/declarations/components/shadowed.d.ts.map +1 -1
  6. package/declarations/index.d.ts +1 -1
  7. package/declarations/index.d.ts.map +1 -1
  8. package/declarations/test-support/dom.d.ts +14 -0
  9. package/declarations/test-support/dom.d.ts.map +1 -0
  10. package/declarations/test-support.d.ts +7 -0
  11. package/declarations/test-support.d.ts.map +1 -0
  12. package/dist/{floating-ui/modifier.js → component-Bs3N-G9z.js} +72 -4
  13. package/dist/component-Bs3N-G9z.js.map +1 -0
  14. package/dist/components/accordion.js +60 -1
  15. package/dist/components/heading.js +74 -7
  16. package/dist/components/one-time-password.js +3 -0
  17. package/dist/components/one-time-password.js.map +1 -0
  18. package/dist/components/popover.js +1 -2
  19. package/dist/components/rating.js +1 -1
  20. package/dist/components/shadowed.js +47 -35
  21. package/dist/components/switch.js +8 -2
  22. package/dist/components/toggle.js +1 -1
  23. package/dist/components/zoetrope.js +1 -1
  24. package/dist/floating-ui.js +1 -2
  25. package/dist/index-D052JWRa.js +149 -0
  26. package/dist/index-D052JWRa.js.map +1 -0
  27. package/dist/{components/zoetrope/index.js → index-DKE67I8L.js} +3 -3
  28. package/dist/index-DKE67I8L.js.map +1 -0
  29. package/dist/index.js +3 -4
  30. package/dist/otp-C6hCCXKx.js +291 -0
  31. package/dist/otp-C6hCCXKx.js.map +1 -0
  32. package/dist/test-support.js +255 -0
  33. package/dist/test-support.js.map +1 -0
  34. package/dist/{components/-private/utils.js → utils-C5796IKA.js} +2 -2
  35. package/dist/utils-C5796IKA.js.map +1 -0
  36. package/package.json +1 -9
  37. package/declarations/components/one-time-password/index.d.ts +0 -3
  38. package/declarations/components/one-time-password/index.d.ts.map +0 -1
  39. package/declarations/test-support/index.d.ts +0 -6
  40. package/declarations/test-support/index.d.ts.map +0 -1
  41. package/dist/components/-private/typed-elements.js +0 -14
  42. package/dist/components/-private/typed-elements.js.map +0 -1
  43. package/dist/components/-private/utils.js.map +0 -1
  44. package/dist/components/accordion/content.js +0 -6
  45. package/dist/components/accordion/content.js.map +0 -1
  46. package/dist/components/accordion/header.js +0 -7
  47. package/dist/components/accordion/header.js.map +0 -1
  48. package/dist/components/accordion/item.js +0 -7
  49. package/dist/components/accordion/item.js.map +0 -1
  50. package/dist/components/accordion/public.js +0 -2
  51. package/dist/components/accordion/public.js.map +0 -1
  52. package/dist/components/accordion/trigger.js +0 -7
  53. package/dist/components/accordion/trigger.js.map +0 -1
  54. package/dist/components/one-time-password/buttons.js +0 -26
  55. package/dist/components/one-time-password/buttons.js.map +0 -1
  56. package/dist/components/one-time-password/index.js +0 -4
  57. package/dist/components/one-time-password/index.js.map +0 -1
  58. package/dist/components/one-time-password/input.js +0 -90
  59. package/dist/components/one-time-password/input.js.map +0 -1
  60. package/dist/components/one-time-password/otp.js +0 -58
  61. package/dist/components/one-time-password/otp.js.map +0 -1
  62. package/dist/components/one-time-password/utils.js +0 -144
  63. package/dist/components/one-time-password/utils.js.map +0 -1
  64. package/dist/components/rating/index.js +0 -45
  65. package/dist/components/rating/index.js.map +0 -1
  66. package/dist/components/rating/public-types.js +0 -2
  67. package/dist/components/rating/public-types.js.map +0 -1
  68. package/dist/components/rating/range.js +0 -15
  69. package/dist/components/rating/range.js.map +0 -1
  70. package/dist/components/rating/stars.js +0 -19
  71. package/dist/components/rating/stars.js.map +0 -1
  72. package/dist/components/rating/state.js +0 -82
  73. package/dist/components/rating/state.js.map +0 -1
  74. package/dist/components/rating/utils.js +0 -18
  75. package/dist/components/rating/utils.js.map +0 -1
  76. package/dist/components/zoetrope/index.js.map +0 -1
  77. package/dist/components/zoetrope/types.js +0 -2
  78. package/dist/components/zoetrope/types.js.map +0 -1
  79. package/dist/floating-ui/component.js +0 -63
  80. package/dist/floating-ui/component.js.map +0 -1
  81. package/dist/floating-ui/middleware.js +0 -15
  82. package/dist/floating-ui/middleware.js.map +0 -1
  83. package/dist/floating-ui/modifier.js.map +0 -1
  84. package/dist/item-CwIzoqlC.js +0 -68
  85. package/dist/item-CwIzoqlC.js.map +0 -1
  86. package/dist/test-support/a11y.js +0 -24
  87. package/dist/test-support/a11y.js.map +0 -1
  88. package/dist/test-support/index.js +0 -7
  89. package/dist/test-support/index.js.map +0 -1
  90. package/dist/test-support/otp.js +0 -34
  91. package/dist/test-support/otp.js.map +0 -1
  92. package/dist/test-support/rating.js +0 -92
  93. package/dist/test-support/rating.js.map +0 -1
  94. package/dist/test-support/routing.js +0 -54
  95. package/dist/test-support/routing.js.map +0 -1
  96. package/dist/test-support/zoetrope.js +0 -43
  97. package/dist/test-support/zoetrope.js.map +0 -1
@@ -0,0 +1,255 @@
1
+
2
+ import { assert } from '@ember/debug';
3
+ import { setupTabster as setupTabster$1 } from './tabster.js';
4
+ import { find, fillIn, settled, findAll, click } from '@ember/test-helpers';
5
+ import Router from '@ember/routing/router';
6
+ import { properLinks } from './proper-links.js';
7
+ import { c } from 'decorator-transforms/runtime';
8
+
9
+ /**
10
+ * Sets up all support utilities for primitive components.
11
+ * Including the tabster root.
12
+ */
13
+ async function setup(owner) {
14
+ await setupTabster$1(owner, {
15
+ setTabsterRoot: false
16
+ });
17
+ document.querySelector('#ember-testing')?.setAttribute('data-tabster', '{ "root": {} }');
18
+ }
19
+ function setupTabster(hooks) {
20
+ hooks.beforeEach(async function () {
21
+ const owner = this.owner;
22
+ assert(`Test does not have an owner, be sure to use setupRenderingTest, setupTest, or setupApplicationTest (from ember-qunit (or similar))`, owner);
23
+ await setup(this.owner);
24
+ });
25
+ }
26
+
27
+ /**
28
+ * Find an element within a shadow-root.
29
+ */
30
+ function findInShadow(root, query) {
31
+ const rootElement = root instanceof Element ? root : find(root);
32
+ return rootElement?.shadowRoot?.querySelector(query);
33
+ }
34
+
35
+ /**
36
+ * Does the element have a shadow root?
37
+ */
38
+ function hasShadowRoot(el) {
39
+ return Boolean(el.shadowRoot);
40
+ }
41
+ function findShadow(root) {
42
+ const rootElement = root ? root instanceof Element ? root : find(root) : document.getElementById('ember-testing');
43
+ if (!rootElement) return;
44
+ for (const element of rootElement.querySelectorAll('*')) {
45
+ if (element.shadowRoot) {
46
+ return element;
47
+ }
48
+ }
49
+ }
50
+ function findInFirstShadow(query) {
51
+ const host = findShadow();
52
+ assert(`No element with a shadow root could be found`, host);
53
+ return findInShadow(host, query);
54
+ }
55
+
56
+ /**
57
+ * @param {string} code the code to fill the input(s) with.
58
+ * @param {string} [ selector ] if there are multiple OTP components on a page, this can be used to select one of them.
59
+ */
60
+ async function fillOTP(code, selector) {
61
+ const ancestor = selector ? find(selector) : document;
62
+ assert(`Could not find ancestor element, does your selector match an existing element?`, ancestor);
63
+ const fieldset = ancestor instanceof HTMLFieldSetElement ? ancestor : ancestor.querySelector('fieldset');
64
+ assert(`Could not find containing fieldset element (this holds the OTP Input fields). Was the OTP component rendered?`, fieldset);
65
+ const inputs = fieldset.querySelectorAll('input');
66
+ assert(`code cannot be longer than the available inputs. code is of length ${code.length} but there are ${inputs.length}`, code.length <= inputs.length);
67
+ const chars = code.split('');
68
+ assert(`OTP Input for index 0 is missing!`, inputs[0]);
69
+ assert(`Character at index 0 is missing`, chars[0]);
70
+ for (let i = 0; i < chars.length; i++) {
71
+ const input = inputs[i];
72
+ const char = chars[i];
73
+ assert(`Input at index ${i} is missing`, input);
74
+ assert(`Character at index ${i} is missing`, char);
75
+ input.value = char;
76
+ }
77
+ await fillIn(inputs[0], chars[0]);
78
+
79
+ // Account for out-of-settled-system delay due to RAF debounce.
80
+ await new Promise(resolve => requestAnimationFrame(resolve));
81
+ await settled();
82
+ }
83
+
84
+ const selectors = {
85
+ root: '.ember-primitives__rating',
86
+ item: '.ember-primitives__rating__item',
87
+ label: '.ember-primitives__rating__label'};
88
+ const stars = {
89
+ selected: '★',
90
+ unselected: '☆'
91
+ };
92
+
93
+ /**
94
+ * Test utility for interacting with the
95
+ * Rating component.
96
+ *
97
+ * Simulates user behavior and provides high level functions so you don't need to worry about the DOM.
98
+ *
99
+ * Actual elements are not exposed, as the elements are private API.
100
+ * Even as you build a design system, the DOM should not be exposed to your consumers.
101
+ */
102
+ function rating(selector) {
103
+ const root = `${selector ?? ''}${selectors.root}`;
104
+ return new RatingPageObject(root);
105
+ }
106
+ class RatingPageObject {
107
+ #root;
108
+ constructor(root) {
109
+ this.#root = root;
110
+ }
111
+ get #rootElement() {
112
+ const element = find(this.#root);
113
+ assert(`Could not find the root element for the <Rating> component. Used the selector \`${this.#root}\`. Was it rendered?`, element);
114
+ return element;
115
+ }
116
+ get #labelElement() {
117
+ const element = find(`${this.#root} ${selectors.label}`);
118
+ assert(`Could not find the label for the <Rating> component. Was it rendered?`, element);
119
+ return element;
120
+ }
121
+ get label() {
122
+ return this.#labelElement.textContent?.replaceAll(/\s+/g, ' ').trim();
123
+ }
124
+ get #starElements() {
125
+ const elements = findAll(`${this.#root} ${selectors.item}`);
126
+ assert(`There are no stars/items. Is the <Rating> component misconfigured?`, elements.length > 0);
127
+ return elements;
128
+ }
129
+ get stars() {
130
+ const elements = this.#starElements;
131
+ return elements.map(x => x.hasAttribute('data-selected') ? stars.selected : stars.unselected).join(' ');
132
+ }
133
+ get starTexts() {
134
+ const elements = this.#starElements;
135
+ return elements.map(x => x.querySelector('[aria-hidden]')?.textContent?.trim()).join(' ');
136
+ }
137
+ get value() {
138
+ const value = this.#rootElement.getAttribute(`data-value`);
139
+ assert(`data-value attribute is missing on element '${this.#root}'`, value);
140
+ const number = parseFloat(value);
141
+ return number;
142
+ }
143
+ get isReadonly() {
144
+ return this.#starElements.every(x => x.hasAttribute('data-readonly'));
145
+ }
146
+ async select(stars) {
147
+ const root = this.#rootElement;
148
+ const star = root.querySelector(`[data-number="${stars}"] input`);
149
+ if (star) {
150
+ await click(star);
151
+ return;
152
+ }
153
+
154
+ /**
155
+ * When we don't have an input, we require an input --
156
+ * which is also the only way we can choose non-integer values.
157
+ *
158
+ * Should be able to be a number input or range input.
159
+ */
160
+ const input = root.querySelector('input[type="number"], input[type="range"]');
161
+ if (input) {
162
+ await fillIn(input, `${stars}`);
163
+ return;
164
+ }
165
+ const available = [...root.querySelectorAll('[data-number]')].map(x => x.getAttribute('data-number'));
166
+ assert(`Could not find item/star in <Rating> with value '${stars}' (or a number or range input with the same "name" value). Is the number (${stars}) correct and in-range for this component? The found available values are ${available.join(', ')}.`);
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Allows setting up routes in tests without the need to scaffold routes in the actual app,
172
+ * allowing for iterating on many different routing scenario / configurations rapidly.
173
+ *
174
+ * Example:
175
+ * ```js
176
+ * import { setupRouting } from 'ember-primitives/test-support';
177
+ *
178
+ * ...
179
+ *
180
+ * test('my test', async function (assert) {
181
+ * setupRouting(this.owner, function () {
182
+ * this.route('foo');
183
+ * this.route('bar', function () {
184
+ * this.route('a');
185
+ * this.route('b');
186
+ * })
187
+ * });
188
+ *
189
+ * await visit('/bar/b');
190
+ * });
191
+ * ```
192
+ *
193
+ */
194
+ function setupRouting(owner, map, options) {
195
+ if (options?.rootURL) {
196
+ assert('rootURL must begin with a forward slash ("/")', options?.rootURL?.startsWith('/'));
197
+ }
198
+ const TestRouter = c(class TestRouter extends Router {
199
+ rootURL = options?.rootURL ?? '/';
200
+ }, [properLinks]);
201
+ TestRouter.map(map);
202
+ owner.register('router:main', TestRouter);
203
+
204
+ // eslint-disable-next-line ember/no-private-routing-service
205
+ const iKnowWhatIMDoing = owner.lookup('router:main');
206
+
207
+ // We need a public testing API for this sort of stuff
208
+
209
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
210
+ iKnowWhatIMDoing.setupRouter();
211
+ }
212
+ function getRouter(owner) {
213
+ return owner.lookup('service:router');
214
+ }
215
+
216
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
217
+ class ZoetropeHelper {
218
+ parentSelector = '.ember-primitives__zoetrope';
219
+ constructor(parentSelector) {
220
+ if (parentSelector) {
221
+ this.parentSelector = parentSelector;
222
+ }
223
+ }
224
+ async scrollLeft() {
225
+ await click(`${this.parentSelector} .ember-primitives__zoetrope__controls button:first-child`);
226
+ }
227
+ async scrollRight() {
228
+ await click(`${this.parentSelector} .ember-primitives__zoetrope__controls button:last-child`);
229
+ }
230
+ visibleItems() {
231
+ const zoetropeContent = document.querySelectorAll(`${this.parentSelector} .ember-primitives__zoetrope__scroller > *`);
232
+ let firstVisibleItemIndex = -1;
233
+ let lastVisibleItemIndex = -1;
234
+ for (let i = 0; i < zoetropeContent.length; i++) {
235
+ const item = zoetropeContent[i];
236
+ const rect = item.getBoundingClientRect();
237
+ const parentRect = item.parentElement.getBoundingClientRect();
238
+ if (rect.right >= parentRect?.left && rect.left <= parentRect?.right) {
239
+ if (firstVisibleItemIndex === -1) {
240
+ firstVisibleItemIndex = i;
241
+ }
242
+ lastVisibleItemIndex = i;
243
+ } else if (firstVisibleItemIndex !== -1) {
244
+ break;
245
+ }
246
+ }
247
+ return Array.from(zoetropeContent).slice(firstVisibleItemIndex, lastVisibleItemIndex + 1);
248
+ }
249
+ visibleItemCount() {
250
+ return this.visibleItems().length;
251
+ }
252
+ }
253
+
254
+ export { ZoetropeHelper, fillOTP, findInFirstShadow, findInShadow, findShadow, getRouter, hasShadowRoot, rating, setupRouting, setupTabster };
255
+ //# sourceMappingURL=test-support.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-support.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -10,5 +10,5 @@ function toggleWithFallback(uncontrolledToggle, controlledToggle, ...args) {
10
10
  uncontrolledToggle(...args);
11
11
  }
12
12
 
13
- export { toggleWithFallback };
14
- //# sourceMappingURL=utils.js.map
13
+ export { toggleWithFallback as t };
14
+ //# sourceMappingURL=utils-C5796IKA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-C5796IKA.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-primitives",
3
- "version": "0.44.0",
3
+ "version": "0.45.1",
4
4
  "description": "Making apps easier to build",
5
5
  "keywords": [
6
6
  "ember-addon"
@@ -82,10 +82,6 @@
82
82
  "types": "./declarations/index.d.ts",
83
83
  "default": "./dist/index.js"
84
84
  },
85
- "./one-time-password": {
86
- "types": "./declarations/components/one-time-password/index.d.ts",
87
- "default": "./dist/components/one-time-password/index.js"
88
- },
89
85
  "./layout/*": {
90
86
  "types": "./declarations/components/layout/*.d.ts",
91
87
  "default": "./dist/components/layout/*.js"
@@ -97,10 +93,6 @@
97
93
  "./*.css": {
98
94
  "default": "./dist/*.css"
99
95
  },
100
- "./test-support": {
101
- "types": "./declarations/test-support/index.d.ts",
102
- "default": "./dist/test-support/index.js"
103
- },
104
96
  "./addon-main": "./addon-main.cjs"
105
97
  },
106
98
  "typesVersions": {
@@ -1,3 +0,0 @@
1
- export { OTPInput } from './input';
2
- export { OTP } from './otp';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/one-time-password/index.gts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC"}
@@ -1,6 +0,0 @@
1
- export { setupTabster } from './a11y.ts';
2
- export { fillOTP } from './otp.ts';
3
- export { rating } from './rating.ts';
4
- export { getRouter, setupRouting } from './routing.ts';
5
- export { ZoetropeHelper } from './zoetrope.ts';
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-support/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
@@ -1,14 +0,0 @@
1
-
2
- import { precompileTemplate } from '@ember/template-compilation';
3
- import { setComponentTemplate } from '@ember/component';
4
- import templateOnly from '@ember/component/template-only';
5
-
6
- const Div = setComponentTemplate(precompileTemplate("\n <div ...attributes>{{yield}}</div>\n", {
7
- strictMode: true
8
- }), templateOnly());
9
- const Label = setComponentTemplate(precompileTemplate("\n <label for={{@for}} ...attributes>{{yield}}</label>\n", {
10
- strictMode: true
11
- }), templateOnly());
12
-
13
- export { Div, Label };
14
- //# sourceMappingURL=typed-elements.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"typed-elements.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,6 +0,0 @@
1
-
2
- import '@glimmer/component';
3
- export { a as AccordionContent, a as default } from '../../item-CwIzoqlC.js';
4
- import '@ember/template-compilation';
5
- import '@ember/component';
6
- //# sourceMappingURL=content.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"content.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,7 +0,0 @@
1
-
2
- import '@ember/helper';
3
- export { c as AccordionHeader, c as default } from '../../item-CwIzoqlC.js';
4
- import '@ember/template-compilation';
5
- import '@ember/component';
6
- import '@ember/component/template-only';
7
- //# sourceMappingURL=header.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"header.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,7 +0,0 @@
1
-
2
- import '@glimmer/component';
3
- import '@ember/helper';
4
- export { A as AccordionItem, A as default, g as getDataState } from '../../item-CwIzoqlC.js';
5
- import '@ember/template-compilation';
6
- import '@ember/component';
7
- //# sourceMappingURL=item.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"item.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
-
2
- //# sourceMappingURL=public.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"public.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,7 +0,0 @@
1
-
2
- import '@ember/modifier';
3
- export { b as AccordionTrigger, b as default } from '../../item-CwIzoqlC.js';
4
- import '@ember/template-compilation';
5
- import '@ember/component';
6
- import '@ember/component/template-only';
7
- //# sourceMappingURL=trigger.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"trigger.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,26 +0,0 @@
1
-
2
- import { assert } from '@ember/debug';
3
- import { on } from '@ember/modifier';
4
- import { precompileTemplate } from '@ember/template-compilation';
5
- import { setComponentTemplate } from '@ember/component';
6
- import templateOnly from '@ember/component/template-only';
7
-
8
- const reset = event => {
9
- assert("[BUG]: reset called without an event.target", event.target instanceof HTMLElement);
10
- const form = event.target.closest("form");
11
- assert("Form is missing. Cannot use <Reset> without being contained within a <form>", form instanceof HTMLFormElement);
12
- form.reset();
13
- };
14
- const Submit = setComponentTemplate(precompileTemplate("\n <button type=\"submit\" ...attributes>Submit</button>\n", {
15
- strictMode: true
16
- }), templateOnly());
17
- const Reset = setComponentTemplate(precompileTemplate("\n <button type=\"button\" {{on \"click\" reset}} ...attributes>{{yield}}</button>\n", {
18
- strictMode: true,
19
- scope: () => ({
20
- on,
21
- reset
22
- })
23
- }), templateOnly());
24
-
25
- export { Reset, Submit };
26
- //# sourceMappingURL=buttons.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"buttons.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,4 +0,0 @@
1
-
2
- export { OTPInput } from './input.js';
3
- export { OTP } from './otp.js';
4
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,90 +0,0 @@
1
-
2
- import Component from '@glimmer/component';
3
- import { warn } from '@ember/debug';
4
- import { isDestroyed, isDestroying } from '@ember/destroyable';
5
- import { on } from '@ember/modifier';
6
- import { buildWaiter } from '@ember/test-waiters';
7
- import { handleNavigation, autoAdvance, handlePaste, selectAll, getCollectiveValue } from './utils.js';
8
- import { precompileTemplate } from '@ember/template-compilation';
9
- import { setComponentTemplate } from '@ember/component';
10
- import templateOnly from '@ember/component/template-only';
11
-
12
- const DEFAULT_LENGTH = 6;
13
- function labelFor(inputIndex, labelFn) {
14
- if (labelFn) {
15
- return labelFn(inputIndex);
16
- }
17
- return `Please enter OTP character ${inputIndex + 1}`;
18
- }
19
- const waiter = buildWaiter("ember-primitives:OTPInput:handleChange");
20
- const Fields = setComponentTemplate(precompileTemplate("\n {{#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=\"off\" ...attributes {{on \"click\" selectAll}} {{on \"paste\" handlePaste}} {{on \"input\" autoAdvance}} {{on \"input\" @handleChange}} {{on \"keydown\" handleNavigation}} />\n </label>\n {{/each}}\n", {
21
- strictMode: true,
22
- scope: () => ({
23
- labelFor,
24
- on,
25
- selectAll,
26
- handlePaste,
27
- autoAdvance,
28
- handleNavigation
29
- })
30
- }), templateOnly());
31
- class OTPInput extends Component {
32
- /**
33
- * This is debounced, because we bind to each input,
34
- * but only want to emit one change event if someone pastes
35
- * multiple characters
36
- */
37
- handleChange = event => {
38
- if (!this.args.onChange) return;
39
- if (!this.#token) {
40
- this.#token = waiter.beginAsync();
41
- }
42
- if (this.#frame) {
43
- cancelAnimationFrame(this.#frame);
44
- }
45
- // We use requestAnimationFrame to be friendly to rendering.
46
- // We don't know if onChange is going to want to cause paints
47
- // (it's also how we debounce, under the assumption that "paste" behavior
48
- // would be fast enough to be quicker than individual frames
49
- // (see logic in autoAdvance)
50
- // )
51
- this.#frame = requestAnimationFrame(() => {
52
- waiter.endAsync(this.#token);
53
- if (isDestroyed(this) || isDestroying(this)) return;
54
- if (!this.args.onChange) return;
55
- const value = getCollectiveValue(event.target, this.length);
56
- if (value === undefined) {
57
- warn(`Value could not be determined for the OTP field. was it removed from the DOM?`, {
58
- id: "ember-primitives.OTPInput.missing-value"
59
- });
60
- return;
61
- }
62
- this.args.onChange({
63
- code: value,
64
- complete: value.length === this.length
65
- }, event);
66
- });
67
- };
68
- #token;
69
- #frame;
70
- get length() {
71
- return this.args.length ?? DEFAULT_LENGTH;
72
- }
73
- get fields() {
74
- // We only need to iterate a number of times,
75
- // so we don't care about the actual value or
76
- // referential integrity here
77
- return new Array(this.length);
78
- }
79
- static {
80
- setComponentTemplate(precompileTemplate("\n <fieldset ...attributes>\n {{#let (component Fields fields=this.fields handleChange=this.handleChange labelFn=@labelFn) as |CurriedFields|}}\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 ", {
81
- strictMode: true,
82
- scope: () => ({
83
- Fields
84
- })
85
- }), this);
86
- }
87
- }
88
-
89
- export { OTPInput };
90
- //# sourceMappingURL=input.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"input.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,58 +0,0 @@
1
-
2
- import { assert } from '@ember/debug';
3
- import { hash, fn } from '@ember/helper';
4
- import { on } from '@ember/modifier';
5
- import { buildWaiter } from '@ember/test-waiters';
6
- import { Reset, Submit } from './buttons.js';
7
- import { OTPInput } from './input.js';
8
- import { precompileTemplate } from '@ember/template-compilation';
9
- import { setComponentTemplate } from '@ember/component';
10
- import templateOnly from '@ember/component/template-only';
11
-
12
- const waiter = buildWaiter("ember-primitives:OTP:handleAutoSubmitAttempt");
13
- const handleFormSubmit = (submit, event) => {
14
- event.preventDefault();
15
- assert("[BUG]: handleFormSubmit was not attached to a form. Please open an issue.", event.currentTarget instanceof HTMLFormElement);
16
- const formData = new FormData(event.currentTarget);
17
- let code = "";
18
- for (const [key, value] of formData.entries()) {
19
- if (key.startsWith("code")) {
20
- // eslint-disable-next-line @typescript-eslint/restrict-plus-operands, @typescript-eslint/no-base-to-string
21
- code += value;
22
- }
23
- }
24
- submit({
25
- code
26
- });
27
- };
28
- function handleChange(autoSubmit, data, event) {
29
- if (!autoSubmit) return;
30
- if (!data.complete) return;
31
- assert("[BUG]: event target is not a known element type", event.target instanceof HTMLElement || event.target instanceof SVGElement);
32
- const form = event.target.closest("form");
33
- assert("[BUG]: Cannot handle event when <OTP> Inputs are not rendered within their <form>", form);
34
- const token = waiter.beginAsync();
35
- const finished = () => {
36
- waiter.endAsync(token);
37
- form.removeEventListener("submit", finished);
38
- };
39
- form.addEventListener("submit", finished);
40
- // NOTE: when calling .submit() the submit event handlers are not run
41
- form.requestSubmit();
42
- }
43
- const OTP = setComponentTemplate(precompileTemplate("\n <form {{on \"submit\" (fn handleFormSubmit @onSubmit)}} ...attributes>\n {{yield (hash Input=(component OTPInput length=@length onChange=(if @autoSubmit (fn handleChange @autoSubmit))) Submit=Submit Reset=Reset)}}\n </form>\n", {
44
- strictMode: true,
45
- scope: () => ({
46
- on,
47
- fn,
48
- handleFormSubmit,
49
- hash,
50
- OTPInput,
51
- handleChange,
52
- Submit,
53
- Reset
54
- })
55
- }), templateOnly());
56
-
57
- export { OTP };
58
- //# sourceMappingURL=otp.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"otp.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}