panelui-native 0.54.0 → 0.57.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.
Files changed (47) hide show
  1. package/README.md +18 -9
  2. package/lib/module/components/combobox/index.js +61 -7
  3. package/lib/module/components/combobox/index.js.map +1 -1
  4. package/lib/module/components/hex-chart/index.js +765 -0
  5. package/lib/module/components/hex-chart/index.js.map +1 -0
  6. package/lib/module/components/qr-code/index.js +641 -0
  7. package/lib/module/components/qr-code/index.js.map +1 -0
  8. package/lib/module/components/qr-code/qr-encode.js +475 -0
  9. package/lib/module/components/qr-code/qr-encode.js.map +1 -0
  10. package/lib/module/components/sortable/index.js +74 -12
  11. package/lib/module/components/sortable/index.js.map +1 -1
  12. package/lib/module/components/steps/index.js +95 -12
  13. package/lib/module/components/steps/index.js.map +1 -1
  14. package/lib/module/components/tag-input/index.js +435 -0
  15. package/lib/module/components/tag-input/index.js.map +1 -0
  16. package/lib/module/components/tour/index.js +661 -0
  17. package/lib/module/components/tour/index.js.map +1 -0
  18. package/lib/module/index.js +4 -0
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/utils/chart.js +209 -0
  21. package/lib/module/utils/chart.js.map +1 -1
  22. package/lib/typescript/src/components/combobox/index.d.ts.map +1 -1
  23. package/lib/typescript/src/components/hex-chart/index.d.ts +277 -0
  24. package/lib/typescript/src/components/hex-chart/index.d.ts.map +1 -0
  25. package/lib/typescript/src/components/qr-code/index.d.ts +221 -0
  26. package/lib/typescript/src/components/qr-code/index.d.ts.map +1 -0
  27. package/lib/typescript/src/components/qr-code/qr-encode.d.ts +39 -0
  28. package/lib/typescript/src/components/qr-code/qr-encode.d.ts.map +1 -0
  29. package/lib/typescript/src/components/sortable/index.d.ts.map +1 -1
  30. package/lib/typescript/src/components/steps/index.d.ts +19 -0
  31. package/lib/typescript/src/components/steps/index.d.ts.map +1 -1
  32. package/lib/typescript/src/components/tag-input/index.d.ts +240 -0
  33. package/lib/typescript/src/components/tag-input/index.d.ts.map +1 -0
  34. package/lib/typescript/src/components/tour/index.d.ts +168 -0
  35. package/lib/typescript/src/components/tour/index.d.ts.map +1 -0
  36. package/lib/typescript/src/index.d.ts +4 -0
  37. package/lib/typescript/src/index.d.ts.map +1 -1
  38. package/lib/typescript/src/utils/chart.d.ts +98 -0
  39. package/lib/typescript/src/utils/chart.d.ts.map +1 -1
  40. package/package.json +1 -1
  41. package/src/components/hex-chart/index.tsx +1009 -0
  42. package/src/components/qr-code/index.tsx +663 -0
  43. package/src/components/qr-code/qr-encode.ts +548 -0
  44. package/src/components/steps/index.tsx +103 -8
  45. package/src/components/tour/index.tsx +933 -0
  46. package/src/index.ts +41 -0
  47. package/src/utils/chart.ts +236 -0
@@ -14,10 +14,24 @@
14
14
  * Steps does not own your flow: it reflects whatever step your app says is
15
15
  * active. Pass `value` to control it, or `defaultValue` to let it manage
16
16
  * its own.
17
+ *
18
+ * The connectors are the component's job, not yours. The root counts the items
19
+ * it holds and each one draws the connector to the next, so a stepper is just
20
+ * its steps — there is no separator to forget, mis-order, or leave dangling
21
+ * past the last stop. An item that contains its own `Steps.Separator` keeps it
22
+ * and gets no second one, so hand-placed connectors still work; `separators`
23
+ * turns the automatic ones off wholesale.
24
+ *
25
+ * Knowing the count is also what lets a step say where it sits. A screen reader
26
+ * reaching the middle of a wizard hears "Payment, step 2 of 3, completed" —
27
+ * the position and the state, which are the two things the circle and its fill
28
+ * convey to everyone else.
17
29
  */
18
30
  import {
31
+ Children,
19
32
  createContext,
20
33
  forwardRef,
34
+ isValidElement,
21
35
  useCallback,
22
36
  useContext,
23
37
  useMemo,
@@ -91,6 +105,7 @@ interface StepsContextValue {
91
105
  activeStep: number;
92
106
  setActiveStep: (step: number) => void;
93
107
  orientation: StepsOrientation;
108
+ separators: boolean;
94
109
  }
95
110
 
96
111
  interface StepItemContextValue {
@@ -100,8 +115,23 @@ interface StepItemContextValue {
100
115
  isLoading: boolean;
101
116
  }
102
117
 
118
+ /**
119
+ * Where an item sits among its siblings, published by the root.
120
+ *
121
+ * Deliberately not the item's own `step` prop: that is the author's numbering
122
+ * of the flow and may skip, repeat or start anywhere, while the connector and
123
+ * the "2 of 3" announcement both need the position in the row as rendered.
124
+ * Absent when an item is used outside a root that maps its children, which is
125
+ * why every reader of it has a fallback.
126
+ */
127
+ interface StepPositionContextValue {
128
+ position: number;
129
+ total: number;
130
+ }
131
+
103
132
  const StepsContext = createContext<StepsContextValue | null>(null);
104
133
  const StepItemContext = createContext<StepItemContextValue | null>(null);
134
+ const StepPositionContext = createContext<StepPositionContextValue | null>(null);
105
135
 
106
136
  function useSteps(component: string): StepsContextValue {
107
137
  const context = useContext(StepsContext);
@@ -127,6 +157,13 @@ export interface StepsProps extends ViewProps {
127
157
  value?: number;
128
158
  onValueChange?: (value: number) => void;
129
159
  orientation?: StepsOrientation;
160
+ /**
161
+ * Draw the connector between one item and the next. On by default — an item
162
+ * that holds its own `Steps.Separator` is left alone either way, so this is
163
+ * for a stepper that wants no connectors at all rather than for one that
164
+ * places them by hand.
165
+ */
166
+ separators?: boolean;
130
167
  children?: ReactNode;
131
168
  }
132
169
 
@@ -138,6 +175,7 @@ const StepsRoot = forwardRef<View, StepsProps>(
138
175
  value,
139
176
  onValueChange,
140
177
  orientation = 'horizontal',
178
+ separators = true,
141
179
  children,
142
180
  ...props
143
181
  },
@@ -156,16 +194,37 @@ const StepsRoot = forwardRef<View, StepsProps>(
156
194
  );
157
195
 
158
196
  const context = useMemo(
159
- () => ({ activeStep, setActiveStep, orientation }),
160
- [activeStep, setActiveStep, orientation]
197
+ () => ({ activeStep, setActiveStep, orientation, separators }),
198
+ [activeStep, setActiveStep, orientation, separators]
161
199
  );
162
200
 
163
201
  const { root } = stepsVariants({ orientation });
164
202
 
203
+ /*
204
+ * Items are counted here rather than registered by each one on mount,
205
+ * because the count has to be right on the first frame: a connector that
206
+ * appears after the last item and disappears once the registrations land
207
+ * is a visible flicker on every mount. Reading the children gives the whole
208
+ * row at once, and a Provider adds no host view, so wrapping an item in one
209
+ * leaves the flex layout exactly as it was.
210
+ */
211
+ const nodes = Children.toArray(textChildren(children));
212
+ const total = nodes.filter((node) => isValidElement(node) && node.type === StepsItem).length;
213
+ let position = -1;
214
+
165
215
  return (
166
216
  <StepsContext.Provider value={context}>
167
217
  <View ref={ref} className={root({ className })} {...props}>
168
- {textChildren(children)}
218
+ {nodes.map((node) => {
219
+ if (!isValidElement(node) || node.type !== StepsItem) return node;
220
+ position += 1;
221
+ const placement = { position, total };
222
+ return (
223
+ <StepPositionContext.Provider key={node.key ?? position} value={placement}>
224
+ {node}
225
+ </StepPositionContext.Provider>
226
+ );
227
+ })}
169
228
  </View>
170
229
  </StepsContext.Provider>
171
230
  );
@@ -190,7 +249,8 @@ const StepsItem = forwardRef<View, StepsItemProps>(
190
249
  { className, step, completed = false, disabled = false, loading = false, children, ...props },
191
250
  ref
192
251
  ) => {
193
- const { activeStep, orientation } = useSteps('Steps.Item');
252
+ const { activeStep, orientation, separators } = useSteps('Steps.Item');
253
+ const placement = useContext(StepPositionContext);
194
254
 
195
255
  const isLoading = loading && step === activeStep;
196
256
  const state: StepState =
@@ -209,10 +269,23 @@ const StepsItem = forwardRef<View, StepsItemProps>(
209
269
 
210
270
  const { item } = stepsVariants({ orientation, state });
211
271
 
272
+ /*
273
+ * The last item has nothing to connect to, and one placed by hand is the
274
+ * author's — adding a second beside it would double the line rather than
275
+ * replace it. Only the top level is inspected, which is where a connector
276
+ * has to be anyway: it is a sibling of the trigger, not something buried
277
+ * inside it.
278
+ */
279
+ const isLast = placement ? placement.position === placement.total - 1 : true;
280
+ const hasOwnSeparator = Children.toArray(children).some(
281
+ (child) => isValidElement(child) && child.type === StepsSeparator
282
+ );
283
+
212
284
  return (
213
285
  <StepItemContext.Provider value={context}>
214
286
  <View ref={ref} className={item({ className })} {...props}>
215
287
  {textChildren(children)}
288
+ {separators && !isLast && !hasOwnSeparator ? <StepsSeparator /> : null}
216
289
  </View>
217
290
  </StepItemContext.Provider>
218
291
  );
@@ -225,18 +298,38 @@ export interface StepsTriggerProps extends ViewProps {
225
298
  children?: ReactNode;
226
299
  }
227
300
 
301
+ /** What each state is called when a screen reader reaches the step. */
302
+ const STATE_WORDS: Record<StepState, string> = {
303
+ completed: 'completed',
304
+ active: 'current step',
305
+ loading: 'in progress',
306
+ inactive: 'not started',
307
+ };
308
+
228
309
  /** Makes its item selectable. Omit it for a read-only stepper. */
229
310
  const StepsTrigger = forwardRef<View, StepsTriggerProps>(
230
311
  ({ className, children, ...props }, ref) => {
231
312
  const { setActiveStep, orientation } = useSteps('Steps.Trigger');
232
313
  const { step, state, isDisabled } = useStepItem('Steps.Trigger');
314
+ const placement = useContext(StepPositionContext);
233
315
  const { trigger } = stepsVariants({ orientation, state, isDisabled });
234
316
 
317
+ /*
318
+ * Said as a value rather than a label, because the label is the step's own
319
+ * title and the circle beside it — text the trigger already merges. An
320
+ * `accessibilityLabel` here would replace all of that with the position,
321
+ * trading the name of the step for its number; a value is read after it.
322
+ */
323
+ const position = placement
324
+ ? `step ${placement.position + 1} of ${placement.total}, ${STATE_WORDS[state]}`
325
+ : STATE_WORDS[state];
326
+
235
327
  return (
236
328
  <Pressable
237
329
  ref={ref}
238
330
  accessibilityRole="button"
239
331
  accessibilityState={{ disabled: isDisabled, selected: state === 'active' }}
332
+ accessibilityValue={{ text: position }}
240
333
  disabled={isDisabled}
241
334
  onPress={() => setActiveStep(step)}
242
335
  className={trigger({ className })}
@@ -310,11 +403,13 @@ export interface StepsSeparatorProps extends ViewProps {
310
403
  }
311
404
 
312
405
  /**
313
- * The connector between two steps. Fills with the primary colour once the
314
- * step before it is complete.
406
+ * The connector between two steps. Fills with the primary colour once the step
407
+ * before it is complete.
315
408
  *
316
- * Place it inside a Steps.Item so it can read that item's state — the
317
- * separator after step 1 goes solid when step 1 is done.
409
+ * Every item draws one automatically, so this is only worth writing to dress a
410
+ * particular connector — an item that holds its own keeps it and gets no
411
+ * second. It belongs inside a `Steps.Item` either way, so it can read that
412
+ * item's state: the connector after step 1 goes solid when step 1 is done.
318
413
  */
319
414
  const StepsSeparator = forwardRef<View, StepsSeparatorProps>(
320
415
  ({ className, ...props }, ref) => {