ember-primitives 0.59.0 → 0.60.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 CHANGED
@@ -46,12 +46,21 @@ See the [Contributing](CONTRIBUTING.md) guide for details.
46
46
  </a>
47
47
  </td>
48
48
  <td align="center">
49
- <a href="https://github.com/lukasnys">
50
- <img src="https://avatars.githubusercontent.com/u/22593230?v=4" width="100;" alt="lukasnys"/>
49
+ <a href="https://github.com/pulien">
50
+ <img src="https://avatars.githubusercontent.com/u/120576344?v=4" width="100;" alt="pulien"/>
51
51
  <br />
52
- <sub><b>Lukas Nys</b></sub>
52
+ <sub><b>pulien</b></sub>
53
53
  </a>
54
54
  </td>
55
+ <td align="center">
56
+ <a href="https://github.com/kaermorchen">
57
+ <img src="https://avatars.githubusercontent.com/u/11972062?v=4" width="100;" alt="kaermorchen"/>
58
+ <br />
59
+ <sub><b>Stanislav Romanov</b></sub>
60
+ </a>
61
+ </td>
62
+ </tr>
63
+ <tr>
55
64
  <td align="center">
56
65
  <a href="https://github.com/rtablada">
57
66
  <img src="https://avatars.githubusercontent.com/u/2532004?v=4" width="100;" alt="rtablada"/>
@@ -59,20 +68,18 @@ See the [Contributing](CONTRIBUTING.md) guide for details.
59
68
  <sub><b>Ryan Tablada</b></sub>
60
69
  </a>
61
70
  </td>
62
- </tr>
63
- <tr>
64
71
  <td align="center">
65
- <a href="https://github.com/kaermorchen">
66
- <img src="https://avatars.githubusercontent.com/u/11972062?v=4" width="100;" alt="kaermorchen"/>
72
+ <a href="https://github.com/lukasnys">
73
+ <img src="https://avatars.githubusercontent.com/u/22593230?v=4" width="100;" alt="lukasnys"/>
67
74
  <br />
68
- <sub><b>Stanislav Romanov</b></sub>
75
+ <sub><b>Lukas Nys</b></sub>
69
76
  </a>
70
77
  </td>
71
78
  <td align="center">
72
- <a href="https://github.com/pulien">
73
- <img src="https://avatars.githubusercontent.com/u/120576344?v=4" width="100;" alt="pulien"/>
79
+ <a href="https://github.com/NullVoxPopuli-ai-agent">
80
+ <img src="https://avatars.githubusercontent.com/u/268630448?v=4" width="100;" alt="NullVoxPopuli-ai-agent"/>
74
81
  <br />
75
- <sub><b>pulien</b></sub>
82
+ <sub><b>@NullVoxPopuli's reduced-access machine account for AI usage</b></sub>
76
83
  </a>
77
84
  </td>
78
85
  <td align="center">
@@ -82,6 +89,13 @@ See the [Contributing](CONTRIBUTING.md) guide for details.
82
89
  <sub><b>Ben Demboski</b></sub>
83
90
  </a>
84
91
  </td>
92
+ <td align="center">
93
+ <a href="https://github.com/bertdeblock">
94
+ <img src="https://avatars.githubusercontent.com/u/7403183?v=4" width="100;" alt="bertdeblock"/>
95
+ <br />
96
+ <sub><b>Bert De Block</b></sub>
97
+ </a>
98
+ </td>
85
99
  <td align="center">
86
100
  <a href="https://github.com/bartocc">
87
101
  <img src="https://avatars.githubusercontent.com/u/47953?v=4" width="100;" alt="bartocc"/>
@@ -89,6 +103,8 @@ See the [Contributing](CONTRIBUTING.md) guide for details.
89
103
  <sub><b>Julien Palmas</b></sub>
90
104
  </a>
91
105
  </td>
106
+ </tr>
107
+ <tr>
92
108
  <td align="center">
93
109
  <a href="https://github.com/mmun">
94
110
  <img src="https://avatars.githubusercontent.com/u/1151810?v=4" width="100;" alt="mmun"/>
@@ -103,8 +119,6 @@ See the [Contributing](CONTRIBUTING.md) guide for details.
103
119
  <sub><b>ember-tomster</b></sub>
104
120
  </a>
105
121
  </td>
106
- </tr>
107
- <tr>
108
122
  <td align="center">
109
123
  <a href="https://github.com/johanrd">
110
124
  <img src="https://avatars.githubusercontent.com/u/4601554?v=4" width="100;" alt="johanrd"/>
@@ -8,7 +8,7 @@ export declare class Heading extends Component<{
8
8
  }> {
9
9
  headingScopeAnchor: Text;
10
10
  constructor(owner: Owner, args: object);
11
- get level(): number;
11
+ get level(): 2 | 1 | 3 | 4 | 5 | 6;
12
12
  get hLevel(): string;
13
13
  }
14
14
  //# sourceMappingURL=heading.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../src/components/heading.gts"],"names":[],"mappings":"AAoCA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAK3C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,qBAAa,OAAQ,SAAQ,SAAS,CAAC;IACrC,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE;QAAE,OAAO,EAAE,EAAE,CAAA;KAAE,CAAC;CACzB,CAAC;IACA,kBAAkB,EAAE,IAAI,CAAC;gBACb,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM;IAMtC,IAAI,KAAK,WAER;IAED,IAAI,MAAM,WAET;CAqBF"}
1
+ {"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../src/components/heading.gts"],"names":[],"mappings":"AAoCA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAK3C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,qBAAa,OAAQ,SAAQ,SAAS,CAAC;IACrC,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE;QAAE,OAAO,EAAE,EAAE,CAAA;KAAE,CAAC;CACzB,CAAC;IACA,kBAAkB,EAAE,IAAI,CAAC;gBACb,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM;IAMtC,IAAI,KAAK,0BAER;IAED,IAAI,MAAM,WAET;CAqBF"}
@@ -1 +1 @@
1
- {"version":3,"file":"incremental-each.d.ts","sourceRoot":"","sources":["../../src/components/incremental-each.gts"],"names":[],"mappings":"AAoSA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAQ3C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAiBtC,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,OAAO;IACpC,IAAI,EAAE;QACJ;;;;;;;;;;;;;;;WAeG;QACH,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;QAEpB;;;;;;;;;;;;;;;;;WAiBG;QACH,SAAS,CAAC,EAAE,MAAM,CAAC;QAEnB;;;;;;;;;;;;;;;;;;;;;;;;;;WA0BG;QACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAE1B;;;;;;;;;;;;;;;;;;;;;;WAsBG;QACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;KACrB,CAAC;IACF,MAAM,EAAE;QACN;;;;;;;;;;;;;WAaG;QACH,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;KACnC,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,eAAe,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;;gBAM3D,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAsCpD,IAAI,CAAC,WAEJ;IAED,IACI,QAAQ;;;;;;QAWX;IA2BD,IAAI,aAIF;IAEF,SAAS,aAYP;CA4BH"}
1
+ {"version":3,"file":"incremental-each.d.ts","sourceRoot":"","sources":["../../src/components/incremental-each.gts"],"names":[],"mappings":"AA6SA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAQ3C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AA0BtC,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,OAAO;IACpC,IAAI,EAAE;QACJ;;;;;;;;;;;;;;;WAeG;QACH,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;QAEpB;;;;;;;;;;;;;;;;;WAiBG;QACH,SAAS,CAAC,EAAE,MAAM,CAAC;QAEnB;;;;;;;;;;;;;;;;;;;;;;;;;;WA0BG;QACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAE1B;;;;;;;;;;;;;;;;;;;;;;WAsBG;QACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;KACrB,CAAC;IACF,MAAM,EAAE;QACN;;;;;;;;;;;;;WAaG;QACH,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;KACnC,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,eAAe,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;;gBAM3D,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAsCpD,IAAI,CAAC,WAEJ;IAED,IACI,QAAQ;;;;;;QAWX;IA2BD,IAAI,aAIF;IAEF,SAAS,aAYP;CA4BH"}
@@ -0,0 +1,64 @@
1
+ import { htmlSafe } from '@ember/template';
2
+ /**
3
+ * `style` attribute values need to be SafeStrings to avoid Ember's
4
+ * style-binding warning.
5
+ */
6
+ export type StyleString = ReturnType<typeof htmlSafe>;
7
+ export interface SliderStoreArgs {
8
+ value?: number | number[];
9
+ min?: number;
10
+ max?: number;
11
+ step?: number | number[];
12
+ orientation?: 'horizontal' | 'vertical';
13
+ disabled?: boolean;
14
+ onValueChange?: (value: number | number[]) => void;
15
+ onValueCommit?: (value: number | number[]) => void;
16
+ }
17
+ export interface SliderThumb {
18
+ index: number;
19
+ value: number;
20
+ /**
21
+ * The value to pass to `<input type="range">`.
22
+ *
23
+ * When using an array `step`, this is the internal index (0..n-1).
24
+ * Otherwise it's the same as `value`.
25
+ */
26
+ inputValue: number;
27
+ percent: number;
28
+ active: boolean;
29
+ /**
30
+ * Inline style positioning this thumb along the track
31
+ * (`left: x%` or `bottom: x%`, depending on orientation).
32
+ */
33
+ positionStyle: StyleString;
34
+ }
35
+ export declare class SliderStore {
36
+ #private;
37
+ activeThumbIndex: number | null;
38
+ constructor(getArgs: () => SliderStoreArgs);
39
+ get min(): number;
40
+ get max(): number;
41
+ get step(): number;
42
+ get tickValues(): number[] | null;
43
+ get orientation(): 'horizontal' | 'vertical';
44
+ get disabled(): boolean;
45
+ get internalMin(): number;
46
+ get internalMax(): number;
47
+ get internalStep(): number;
48
+ get internalValues(): number[];
49
+ outputValuesFromInternal(internalValues: number[]): number[];
50
+ get values(): number[];
51
+ get thumbs(): SliderThumb[];
52
+ get thumbPercents(): number[];
53
+ get isMulti(): boolean;
54
+ thumbPositionStyle: (percent: number) => StyleString;
55
+ get rangeStyle(): StyleString;
56
+ updateValue: (newValues: number[]) => void;
57
+ commitValue: (newValues: number[]) => void;
58
+ coerceOutput(values: number[]): number | number[];
59
+ handleThumbInput: (index: number, value: number) => void;
60
+ handleThumbChange: (index: number, value: number) => void;
61
+ handleThumbActivate: (index: number) => void;
62
+ defaultThumbLabel: (index: number) => string;
63
+ }
64
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/components/slider/store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IACnD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,aAAa,EAAE,WAAW,CAAC;CAC5B;AA+FD,qBAAa,WAAW;;IAIb,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAQ;gBAEpC,OAAO,EAAE,MAAM,eAAe;IAgB1C,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,UAAU,IAAI,MAAM,EAAE,GAAG,IAAI,CAShC;IAED,IAAI,WAAW,IAAI,YAAY,GAAG,UAAU,CAE3C;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,WAAW,IAAI,MAAM,CAMxB;IAED,IAAI,WAAW,IAAI,MAAM,CAMxB;IAED,IAAI,YAAY,IAAI,MAAM,CAMzB;IAED,IAAI,cAAc,IAAI,MAAM,EAAE,CAiB7B;IAED,wBAAwB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;IAY5D,IAAI,MAAM,IAAI,MAAM,EAAE,CAErB;IAED,IAAI,MAAM,IAAI,WAAW,EAAE,CAI1B;IAED,IAAI,aAAa,IAAI,MAAM,EAAE,CAI5B;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,kBAAkB,GAAI,SAAS,MAAM,KAAG,WAAW,CAIjD;IAEF,IAAI,UAAU,IAAI,WAAW,CAiB5B;IAED,WAAW,GAAI,WAAW,MAAM,EAAE,UAIhC;IAEF,WAAW,GAAI,WAAW,MAAM,EAAE,UAIhC;IAEF,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE;IA6CjD,gBAAgB,GAAI,OAAO,MAAM,EAAE,OAAO,MAAM,UAO9C;IAEF,iBAAiB,GAAI,OAAO,MAAM,EAAE,OAAO,MAAM,UAQ/C;IAEF,mBAAmB,GAAI,OAAO,MAAM,UAElC;IAEF,iBAAiB,GAAI,OAAO,MAAM,KAAG,MAAM,CAOzC;CACH"}
@@ -0,0 +1,150 @@
1
+ import "./slider.css";
2
+ import Component from "@glimmer/component";
3
+ import { SliderStore, type SliderThumb, type StyleString } from "./slider/store.ts";
4
+ import type { TOC } from "@ember/component/template-only";
5
+ import type Owner from "@ember/owner";
6
+ import type { WithBoundArgs } from "@glint/template";
7
+ export type { SliderThumb };
8
+ export interface Signature {
9
+ Element: HTMLSpanElement;
10
+ Args: {
11
+ /**
12
+ * The current value(s) of the slider.
13
+ * For single value slider, pass a single number.
14
+ * For range slider, pass an array of numbers [min, max].
15
+ */
16
+ value?: number | number[];
17
+ /**
18
+ * The minimum value of the slider.
19
+ * Defaults to 0.
20
+ */
21
+ min?: number;
22
+ /**
23
+ * The maximum value of the slider.
24
+ * Defaults to 100.
25
+ */
26
+ max?: number;
27
+ /**
28
+ * The stepping interval.
29
+ *
30
+ * When passed a number, the slider moves in fixed increments.
31
+ * When passed an array of numbers, the slider snaps to those discrete values.
32
+ * Defaults to 1.
33
+ */
34
+ step?: number | number[];
35
+ /**
36
+ * The orientation of the slider.
37
+ * Defaults to 'horizontal'.
38
+ */
39
+ orientation?: "horizontal" | "vertical";
40
+ /**
41
+ * Whether the slider is disabled.
42
+ */
43
+ disabled?: boolean;
44
+ /**
45
+ * Callback when the value changes during dragging.
46
+ */
47
+ onValueChange?: (value: number | number[]) => void;
48
+ /**
49
+ * Callback when the value is committed (after dragging ends).
50
+ */
51
+ onValueCommit?: (value: number | number[]) => void;
52
+ };
53
+ Blocks: {
54
+ default: [
55
+ {
56
+ /**
57
+ * The track element - the rail along which the thumb moves
58
+ */
59
+ Track: typeof Track;
60
+ /**
61
+ * The range element - the filled portion of the track
62
+ */
63
+ Range: WithBoundArgs<typeof Range, "rangeStyle">;
64
+ /**
65
+ * The thumb element - the draggable handle(s)
66
+ */
67
+ Thumb: WithBoundArgs<typeof ThumbComponent, "store">;
68
+ /**
69
+ * The current value(s)
70
+ */
71
+ values: number[];
72
+ /**
73
+ * The tick values, if any.
74
+ */
75
+ tickValues: number[] | null;
76
+ /**
77
+ * A stable list of thumbs to iterate over.
78
+ * Prefer this over iterating `values` directly to avoid DOM churn during dragging.
79
+ */
80
+ thumbs: SliderThumb[];
81
+ /**
82
+ * The minimum value
83
+ */
84
+ min: number;
85
+ /**
86
+ * The maximum value
87
+ */
88
+ max: number;
89
+ /**
90
+ * The step value
91
+ */
92
+ step: number;
93
+ }
94
+ ];
95
+ };
96
+ }
97
+ interface TrackSignature {
98
+ Element: HTMLSpanElement;
99
+ Args: Record<string, never>;
100
+ Blocks: {
101
+ default: [];
102
+ };
103
+ }
104
+ declare const Track: TOC<TrackSignature>;
105
+ interface RangeSignature {
106
+ Element: HTMLSpanElement;
107
+ Args: {
108
+ rangeStyle: StyleString;
109
+ };
110
+ }
111
+ declare const Range: TOC<RangeSignature>;
112
+ declare class ThumbComponent extends Component<{
113
+ /**
114
+ * `...attributes` land on the invisible native input, which is the
115
+ * interactive element (pass `aria-label` / `aria-labelledby` here).
116
+ */
117
+ Element: HTMLInputElement;
118
+ Args: {
119
+ store: SliderStore;
120
+ /**
121
+ * Optional convenience: pass the full thumb object instead of `@value` + `@index`.
122
+ */
123
+ thumb?: SliderThumb;
124
+ value?: number;
125
+ index?: number;
126
+ };
127
+ Blocks: {
128
+ /**
129
+ * Rendered inside the visual thumb — useful for tooltips / value labels.
130
+ */
131
+ default: [];
132
+ };
133
+ }> {
134
+ get index(): number;
135
+ get value(): number;
136
+ get isActive(): boolean;
137
+ get positionStyle(): import("@ember/-internals/glimmer/lib/utils/string").TrustedHTML;
138
+ private readValue;
139
+ private onInput;
140
+ private onChange;
141
+ private onPointerUp;
142
+ private onGotPointerCapture;
143
+ private onFocus;
144
+ }
145
+ export declare class Slider extends Component<Signature> {
146
+ store: SliderStore;
147
+ constructor(owner: Owner, args: Signature["Args"]);
148
+ }
149
+ export default Slider;
150
+ //# sourceMappingURL=slider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slider.d.ts","sourceRoot":"","sources":["../../src/components/slider.gts"],"names":[],"mappings":"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"}
@@ -21,6 +21,7 @@ export { Rating } from './components/rating';
21
21
  export { Scroller } from './components/scroller';
22
22
  export { Separator } from './components/separator';
23
23
  export { Shadowed } from './components/shadowed';
24
+ export { Slider } from './components/slider';
24
25
  export { Switch } from './components/switch';
25
26
  export { Toggle } from './components/toggle';
26
27
  export { ToggleGroup } from './components/toggle-group';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,YAAY,EACV,iCAAiC,EACjC,gCAAgC,EAChC,8BAA8B,EAC9B,iCAAiC,GAClC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,YAAY,EACV,iCAAiC,EACjC,gCAAgC,EAChC,8BAA8B,EAC9B,iCAAiC,GAClC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,cAAc,cAAc,CAAC"}
@@ -18,6 +18,14 @@ function chunk(arr, size) {
18
18
  }
19
19
  return out;
20
20
  }
21
+ // Safari has `requestIdleCallback` behind a flag, effectively absent
22
+ // for end users. Fall back to `setTimeout(cb, 0)` — Safari users get
23
+ // the chunking benefit (one batch per task) without the idle-priority
24
+ // hint that other browsers honor.
25
+ const ric = typeof requestIdleCallback === "function" ? requestIdleCallback : cb => setTimeout(() => cb({
26
+ timeRemaining: () => 0,
27
+ didTimeout: true
28
+ }), 0);
21
29
  /**
22
30
  * A drop-in replacement for `{{#each}}` that renders a large collection
23
31
  * a batch at a time on each animation frame, instead of all at once.
@@ -122,7 +130,7 @@ class IncrementalEach extends Component {
122
130
  // otherwise tracked-value backtracking asserts.
123
131
  tick = () => {
124
132
  if (this.#items.length > this.#count.current) {
125
- requestIdleCallback(() => this.#count.current++, {
133
+ ric(() => this.#count.current++, {
126
134
  timeout: 10
127
135
  });
128
136
  }
@@ -1 +1 @@
1
- {"version":3,"file":"incremental-each.js","sources":["../../src/components/incremental-each.gts"],"sourcesContent":["import Component from \"@glimmer/component\";\nimport { cached } from \"@glimmer/tracking\";\nimport { assert } from \"@ember/debug\";\nimport { isDestroyed, isDestroying, registerDestructor } from \"@ember/destroyable\";\nimport { buildWaiter } from \"@ember/test-waiters\";\n\nimport { cell } from \"ember-resources\";\n\nimport type Owner from \"@ember/owner\";\n\nconst DEFAULT_BATCH_SIZE = 50;\nconst DEFAULT_INITIAL = \"sync\";\n\nconst waiter = buildWaiter(\"ember-primitives:incremental-each\");\n\nfunction chunk<T>(arr: readonly T[], size: number): T[][] {\n const out: T[][] = [];\n\n for (let i = 0; i < arr.length; i += size) {\n out.push(arr.slice(i, i + size));\n }\n\n return out;\n}\n\nexport interface Signature<T = unknown> {\n Args: {\n /**\n * The collection of items to render.\n *\n * Replacing the array (new identity) restarts rendering from the\n * first batch.\n *\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <IncrementalEach @items={{this.rows}} as |row|>\n * <my-row @row={{row}} />\n * </IncrementalEach>\n * </template>\n * ```\n */\n items: readonly T[];\n\n /**\n * How many items to add per animation frame.\n *\n * Larger batches add more items per chunk; smaller batches yield to\n * the browser more often.\n *\n * Default: 50. Must be positive; `0` or less asserts in development.\n *\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <IncrementalEach @items={{this.rows}} @batchSize={{100}} as |row|>\n * <my-row @row={{row}} />\n * </IncrementalEach>\n * </template>\n * ```\n */\n batchSize?: number;\n\n /**\n * Controls how the initial batch is committed.\n *\n * - `\"sync\"` (default): the first `@batchSize` items render in the\n * same render pass as mount / `@items` change. The user sees\n * content on the very first paint, and the rest of the list\n * fills in one batch per animation frame. This is the right\n * default for most lists — even a perceived \"empty for one\n * frame\" is worse than rendering a few extra items synchronously.\n * - `\"lazy\"`: even the first batch waits for an animation frame, so\n * the initial paint is empty and content arrives one batch per\n * frame. Use this when the first batch itself would be expensive\n * enough to block the first paint, and you'd rather show an\n * empty container than delay it.\n *\n * Default: `\"sync\"`.\n *\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <IncrementalEach @items={{this.rows}} @initial=\"lazy\" as |row|>\n * <my-row @row={{row}} />\n * </IncrementalEach>\n * </template>\n * ```\n */\n initial?: \"sync\" | \"lazy\";\n\n /**\n * Called once with no arguments when every item in `@items` has\n * been committed to the DOM. Fires after the final batch lands;\n * does not fire on intermediate batches.\n *\n * Fires again on a fresh swap (new `@items` identity) once that\n * new collection finishes rendering. An empty `@items` array\n * does not fire the callback.\n *\n * Useful for marking the list as ready for screenshot tests,\n * dismissing a loading indicator, or measuring how long the\n * whole render took.\n *\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <IncrementalEach @items={{this.rows}} @onDone={{this.handleDone}} as |row|>\n * <my-row @row={{row}} />\n * </IncrementalEach>\n * </template>\n * ```\n */\n onDone?: () => void;\n };\n Blocks: {\n /**\n * Yielded for each rendered item, with the index in the original\n * `@items` array.\n *\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <IncrementalEach @items={{this.rows}} as |row index|>\n * {{index}}: {{row.label}}\n * </IncrementalEach>\n * </template>\n * ```\n */\n default: [item: T, index: number];\n };\n}\n\n/**\n * A drop-in replacement for `{{#each}}` that renders a large collection\n * a batch at a time on each animation frame, instead of all at once.\n *\n * Every item ends up in the DOM, so browser find (Ctrl+F / Cmd+F), anchor\n * links, screen readers, print, and SEO all work against the full list.\n * Yielding the main thread between batches keeps the page responsive while\n * the rest of the list is filling in.\n *\n * By default the first batch lands synchronously, so the user sees content\n * on the very first paint. Pass `@initial=\"lazy\"` to defer the first batch\n * to an animation frame as well.\n *\n * Intended for non-scrollable containers, or anywhere a virtual/windowed\n * list does not apply (variable item heights, lists that grow the page,\n * surfaces that need every row indexable).\n *\n * Do not nest one `<IncrementalEach>` inside another. Each level adds an\n * animation-frame delay before its content paints; nesting compounds those\n * delays, so inner rows appear to flicker in with missing sub-content.\n * If you have nested loops, only the outermost one should be\n * `<IncrementalEach>`; leave deeper loops as plain `{{#each}}`.\n *\n * @example\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <ul>\n * <IncrementalEach @items={{this.rows}} @batchSize={{100}} as |row index|>\n * <li>{{index}}: {{row.label}}</li>\n * </IncrementalEach>\n * </ul>\n * </template>\n * ```\n */\nexport class IncrementalEach<T = unknown> extends Component<Signature<T>> {\n #count = cell(0);\n #itemsRef: readonly T[] | null = null;\n #waiterToken: unknown = null;\n #doneFor: object | null = null;\n\n constructor(owner: Owner, args: Signature<T>[\"Args\"]) {\n super(owner, args);\n\n registerDestructor(this, () => this.#endWaiter());\n }\n\n // Reset progress and (re)open the test-waiter when `@items` identity\n // changes, so a swap restarts at the first batch, `@onDone` can fire\n // again for the new collection, and `await settled()` knows to wait\n // until `checkDone` closes the waiter. Mutating from a getter is safe\n // here because the writes happen before any consumer reads them in\n // the same render pass.\n /* eslint-disable ember/no-side-effects */\n get #items(): readonly T[] {\n const items = this.args.items;\n\n assert(`@items must be an array`, items);\n\n if (items !== this.#itemsRef) {\n this.#itemsRef = items;\n this.#count.current = 0;\n this.#endWaiter();\n\n if (items.length > 0) {\n this.#waiterToken = waiter.beginAsync();\n }\n }\n\n return items;\n }\n /* eslint-enable ember/no-side-effects */\n\n // `\"sync\"` keeps bucket 0 visible at count=0 (`i = 0 >= 0`); `\"lazy\"`\n // starts one step behind so even bucket 0 needs a tick.\n get #start() {\n return this.#initial === \"sync\" ? 0 : -1;\n }\n\n get i() {\n return this.#start + this.#count.current;\n }\n\n @cached\n get bucketed() {\n const size = this.#batchSize;\n\n return chunk(this.#items, size).map((items, b) => {\n const start = b * size;\n\n return {\n isReady: () => this.i >= b,\n items: items.map((value, j) => ({ value, index: start + j })),\n };\n });\n }\n\n get #batchSize(): number {\n const requested = this.args.batchSize ?? DEFAULT_BATCH_SIZE;\n\n assert(\n `<IncrementalEach> @batchSize must be a positive number, got ${requested}`,\n requested > 0,\n );\n\n return requested;\n }\n\n get #initial(): \"sync\" | \"lazy\" {\n const requested = this.args.initial ?? DEFAULT_INITIAL;\n\n assert(\n `<IncrementalEach> @initial must be \"sync\" or \"lazy\", got ${requested}`,\n requested === \"sync\" || requested === \"lazy\",\n );\n\n return requested;\n }\n\n // `#items` is read before `#count` so the count-reset inside `#items`\n // (on `@items` swap) lands before this read of count this render —\n // otherwise tracked-value backtracking asserts.\n tick = () => {\n if (this.#items.length > this.#count.current) {\n requestIdleCallback(() => this.#count.current++, { timeout: 10 });\n }\n };\n\n checkDone = () => {\n const bucketed = this.bucketed;\n\n if (this.#doneFor === bucketed) return;\n if (this.i < bucketed.length - 1) return;\n\n this.#doneFor = bucketed;\n queueMicrotask(() => {\n if (isDestroyed(this) || isDestroying(this)) return;\n this.args.onDone?.();\n this.#endWaiter();\n });\n };\n\n #endWaiter() {\n if (this.#waiterToken) waiter.endAsync(this.#waiterToken);\n }\n\n <template>\n {{(this.tick)}}{{#each this.bucketed as |bucket|}}{{#if (bucket.isReady)}}{{#each\n bucket.items\n as |entry|\n }}{{yield entry.value entry.index}}{{/each}}{{(this.checkDone)}}{{/if}}{{/each}}\n </template>\n}\n"],"names":["DEFAULT_BATCH_SIZE","DEFAULT_INITIAL","waiter","buildWaiter","chunk","arr","size","out","i","length","push","slice","IncrementalEach","Component","cell","constructor","owner","args","registerDestructor","#items","items","assert","current","beginAsync","#start","bucketed","map","b","start","isReady","value","j","index","n","prototype","cached","#batchSize","requested","batchSize","#initial","initial","tick","requestIdleCallback","timeout","checkDone","queueMicrotask","isDestroyed","isDestroying","onDone","#endWaiter","endAsync","setComponentTemplate","precompileTemplate","strictMode"],"mappings":"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"}
1
+ {"version":3,"file":"incremental-each.js","sources":["../../src/components/incremental-each.gts"],"sourcesContent":["import Component from \"@glimmer/component\";\nimport { cached } from \"@glimmer/tracking\";\nimport { assert } from \"@ember/debug\";\nimport { isDestroyed, isDestroying, registerDestructor } from \"@ember/destroyable\";\nimport { buildWaiter } from \"@ember/test-waiters\";\n\nimport { cell } from \"ember-resources\";\n\nimport type Owner from \"@ember/owner\";\n\nconst DEFAULT_BATCH_SIZE = 50;\nconst DEFAULT_INITIAL = \"sync\";\n\nconst waiter = buildWaiter(\"ember-primitives:incremental-each\");\n\nfunction chunk<T>(arr: readonly T[], size: number): T[][] {\n const out: T[][] = [];\n\n for (let i = 0; i < arr.length; i += size) {\n out.push(arr.slice(i, i + size));\n }\n\n return out;\n}\n\n// Safari has `requestIdleCallback` behind a flag, effectively absent\n// for end users. Fall back to `setTimeout(cb, 0)` — Safari users get\n// the chunking benefit (one batch per task) without the idle-priority\n// hint that other browsers honor.\nconst ric: typeof requestIdleCallback =\n typeof requestIdleCallback === \"function\"\n ? requestIdleCallback\n : (cb) => setTimeout(() => cb({ timeRemaining: () => 0, didTimeout: true }), 0);\n\nexport interface Signature<T = unknown> {\n Args: {\n /**\n * The collection of items to render.\n *\n * Replacing the array (new identity) restarts rendering from the\n * first batch.\n *\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <IncrementalEach @items={{this.rows}} as |row|>\n * <my-row @row={{row}} />\n * </IncrementalEach>\n * </template>\n * ```\n */\n items: readonly T[];\n\n /**\n * How many items to add per animation frame.\n *\n * Larger batches add more items per chunk; smaller batches yield to\n * the browser more often.\n *\n * Default: 50. Must be positive; `0` or less asserts in development.\n *\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <IncrementalEach @items={{this.rows}} @batchSize={{100}} as |row|>\n * <my-row @row={{row}} />\n * </IncrementalEach>\n * </template>\n * ```\n */\n batchSize?: number;\n\n /**\n * Controls how the initial batch is committed.\n *\n * - `\"sync\"` (default): the first `@batchSize` items render in the\n * same render pass as mount / `@items` change. The user sees\n * content on the very first paint, and the rest of the list\n * fills in one batch per animation frame. This is the right\n * default for most lists — even a perceived \"empty for one\n * frame\" is worse than rendering a few extra items synchronously.\n * - `\"lazy\"`: even the first batch waits for an animation frame, so\n * the initial paint is empty and content arrives one batch per\n * frame. Use this when the first batch itself would be expensive\n * enough to block the first paint, and you'd rather show an\n * empty container than delay it.\n *\n * Default: `\"sync\"`.\n *\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <IncrementalEach @items={{this.rows}} @initial=\"lazy\" as |row|>\n * <my-row @row={{row}} />\n * </IncrementalEach>\n * </template>\n * ```\n */\n initial?: \"sync\" | \"lazy\";\n\n /**\n * Called once with no arguments when every item in `@items` has\n * been committed to the DOM. Fires after the final batch lands;\n * does not fire on intermediate batches.\n *\n * Fires again on a fresh swap (new `@items` identity) once that\n * new collection finishes rendering. An empty `@items` array\n * does not fire the callback.\n *\n * Useful for marking the list as ready for screenshot tests,\n * dismissing a loading indicator, or measuring how long the\n * whole render took.\n *\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <IncrementalEach @items={{this.rows}} @onDone={{this.handleDone}} as |row|>\n * <my-row @row={{row}} />\n * </IncrementalEach>\n * </template>\n * ```\n */\n onDone?: () => void;\n };\n Blocks: {\n /**\n * Yielded for each rendered item, with the index in the original\n * `@items` array.\n *\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <IncrementalEach @items={{this.rows}} as |row index|>\n * {{index}}: {{row.label}}\n * </IncrementalEach>\n * </template>\n * ```\n */\n default: [item: T, index: number];\n };\n}\n\n/**\n * A drop-in replacement for `{{#each}}` that renders a large collection\n * a batch at a time on each animation frame, instead of all at once.\n *\n * Every item ends up in the DOM, so browser find (Ctrl+F / Cmd+F), anchor\n * links, screen readers, print, and SEO all work against the full list.\n * Yielding the main thread between batches keeps the page responsive while\n * the rest of the list is filling in.\n *\n * By default the first batch lands synchronously, so the user sees content\n * on the very first paint. Pass `@initial=\"lazy\"` to defer the first batch\n * to an animation frame as well.\n *\n * Intended for non-scrollable containers, or anywhere a virtual/windowed\n * list does not apply (variable item heights, lists that grow the page,\n * surfaces that need every row indexable).\n *\n * Do not nest one `<IncrementalEach>` inside another. Each level adds an\n * animation-frame delay before its content paints; nesting compounds those\n * delays, so inner rows appear to flicker in with missing sub-content.\n * If you have nested loops, only the outermost one should be\n * `<IncrementalEach>`; leave deeper loops as plain `{{#each}}`.\n *\n * @example\n * ```gjs\n * import { IncrementalEach } from 'ember-primitives';\n *\n * <template>\n * <ul>\n * <IncrementalEach @items={{this.rows}} @batchSize={{100}} as |row index|>\n * <li>{{index}}: {{row.label}}</li>\n * </IncrementalEach>\n * </ul>\n * </template>\n * ```\n */\nexport class IncrementalEach<T = unknown> extends Component<Signature<T>> {\n #count = cell(0);\n #itemsRef: readonly T[] | null = null;\n #waiterToken: unknown = null;\n #doneFor: object | null = null;\n\n constructor(owner: Owner, args: Signature<T>[\"Args\"]) {\n super(owner, args);\n\n registerDestructor(this, () => this.#endWaiter());\n }\n\n // Reset progress and (re)open the test-waiter when `@items` identity\n // changes, so a swap restarts at the first batch, `@onDone` can fire\n // again for the new collection, and `await settled()` knows to wait\n // until `checkDone` closes the waiter. Mutating from a getter is safe\n // here because the writes happen before any consumer reads them in\n // the same render pass.\n /* eslint-disable ember/no-side-effects */\n get #items(): readonly T[] {\n const items = this.args.items;\n\n assert(`@items must be an array`, items);\n\n if (items !== this.#itemsRef) {\n this.#itemsRef = items;\n this.#count.current = 0;\n this.#endWaiter();\n\n if (items.length > 0) {\n this.#waiterToken = waiter.beginAsync();\n }\n }\n\n return items;\n }\n /* eslint-enable ember/no-side-effects */\n\n // `\"sync\"` keeps bucket 0 visible at count=0 (`i = 0 >= 0`); `\"lazy\"`\n // starts one step behind so even bucket 0 needs a tick.\n get #start() {\n return this.#initial === \"sync\" ? 0 : -1;\n }\n\n get i() {\n return this.#start + this.#count.current;\n }\n\n @cached\n get bucketed() {\n const size = this.#batchSize;\n\n return chunk(this.#items, size).map((items, b) => {\n const start = b * size;\n\n return {\n isReady: () => this.i >= b,\n items: items.map((value, j) => ({ value, index: start + j })),\n };\n });\n }\n\n get #batchSize(): number {\n const requested = this.args.batchSize ?? DEFAULT_BATCH_SIZE;\n\n assert(\n `<IncrementalEach> @batchSize must be a positive number, got ${requested}`,\n requested > 0,\n );\n\n return requested;\n }\n\n get #initial(): \"sync\" | \"lazy\" {\n const requested = this.args.initial ?? DEFAULT_INITIAL;\n\n assert(\n `<IncrementalEach> @initial must be \"sync\" or \"lazy\", got ${requested}`,\n requested === \"sync\" || requested === \"lazy\",\n );\n\n return requested;\n }\n\n // `#items` is read before `#count` so the count-reset inside `#items`\n // (on `@items` swap) lands before this read of count this render —\n // otherwise tracked-value backtracking asserts.\n tick = () => {\n if (this.#items.length > this.#count.current) {\n ric(() => this.#count.current++, { timeout: 10 });\n }\n };\n\n checkDone = () => {\n const bucketed = this.bucketed;\n\n if (this.#doneFor === bucketed) return;\n if (this.i < bucketed.length - 1) return;\n\n this.#doneFor = bucketed;\n queueMicrotask(() => {\n if (isDestroyed(this) || isDestroying(this)) return;\n this.args.onDone?.();\n this.#endWaiter();\n });\n };\n\n #endWaiter() {\n if (this.#waiterToken) waiter.endAsync(this.#waiterToken);\n }\n\n <template>\n {{(this.tick)}}{{#each this.bucketed as |bucket|}}{{#if (bucket.isReady)}}{{#each\n bucket.items\n as |entry|\n }}{{yield entry.value entry.index}}{{/each}}{{(this.checkDone)}}{{/if}}{{/each}}\n </template>\n}\n"],"names":["DEFAULT_BATCH_SIZE","DEFAULT_INITIAL","waiter","buildWaiter","chunk","arr","size","out","i","length","push","slice","ric","requestIdleCallback","cb","setTimeout","timeRemaining","didTimeout","IncrementalEach","Component","cell","constructor","owner","args","registerDestructor","#items","items","assert","current","beginAsync","#start","bucketed","map","b","start","isReady","value","j","index","n","prototype","cached","#batchSize","requested","batchSize","#initial","initial","tick","timeout","checkDone","queueMicrotask","isDestroyed","isDestroying","onDone","#endWaiter","endAsync","setComponentTemplate","precompileTemplate","strictMode"],"mappings":"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"}