@wix/himalaya-cli 0.942.0 → 0.944.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/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +6 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/bookings-v2/src/index.d.ts +10 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/wix-data/src/index.d.ts +50 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-data.mjs +16 -2
- package/dist/cli.mjs +20 -15
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/component-reference.json +372 -1
- package/guides/component-reference.md +215 -0
- package/guides/recipe-dynamic-list.md +45 -2
- package/guides/sdk-reference.json +45 -21
- package/package.json +2 -2
- package/templates/beauty-salon/tier5-src/wix-spaces-collections/index.ts +60 -12
- package/templates/branded-lite/tier5-src/wix-spaces-collections/index.ts +60 -12
- package/templates/gym-fitness/tier5-src/wix-spaces-collections/index.ts +60 -12
- package/templates/portfolio-creative/tier5-src/wix-spaces-collections/index.ts +60 -12
- package/templates/retail-store/tier5-src/wix-spaces-collections/index.ts +60 -12
|
@@ -180,6 +180,36 @@ The two share a leaf name and mean opposite things — descriptor side takes the
|
|
|
180
180
|
registry takes the HEX — so a validator error about `shadows.card.color` is not this table
|
|
181
181
|
contradicting itself.
|
|
182
182
|
|
|
183
|
+
## What a control sends (action payloads)
|
|
184
|
+
|
|
185
|
+
A component's props say what it READS. This says what it SENDS: the value a control injects
|
|
186
|
+
into the `Action` it dispatches, so a Tier-5 reducer can be written from this page instead of
|
|
187
|
+
from trial and error.
|
|
188
|
+
|
|
189
|
+
1. **The payload is in `args`.** `Action.args` is a `Value`, so it holds the real type
|
|
190
|
+
(bool / int / double / array), and every host merges `{...params, ...args}` with `args`
|
|
191
|
+
winning. Read `args` first.
|
|
192
|
+
2. **`params` may mirror it, but only for a string.** `Action.params` is declared
|
|
193
|
+
`map<string,string>` in the descriptor schema; a number, bool or array there is a type
|
|
194
|
+
violation even where JavaScript tolerates it.
|
|
195
|
+
3. **The key and the encoding below are normative.** A renderer that sends a different key —
|
|
196
|
+
or no payload at all — is a divergence, and every one that exists today is printed with the
|
|
197
|
+
component it affects, because that is precisely the case a reducer has to be written around.
|
|
198
|
+
|
|
199
|
+
Every row here is generated from the platform's own payload contract and re-checked against
|
|
200
|
+
all four renderers on every build, so it cannot drift from what the components actually send.
|
|
201
|
+
|
|
202
|
+
**What it covers, and what it does not.** The contract is about **value controls** — the ones
|
|
203
|
+
whose callback carries the thing the user chose or typed. A value callback absent from a
|
|
204
|
+
component's block injects nothing: it dispatches the author's action verbatim, so any
|
|
205
|
+
discriminator must come from the `args` the author wrote (`Chip.onRemove` and
|
|
206
|
+
`DisclosureGroup.onToggle` are the two that work this way today).
|
|
207
|
+
|
|
208
|
+
That is NOT a statement about every action a component can fire. Gesture and event callbacks —
|
|
209
|
+
`Map.onMapTap` / `onMarkerTap`, a media player's progress events — inject payloads of their
|
|
210
|
+
own and are outside this contract, so read the component's own prop documentation for those
|
|
211
|
+
rather than concluding from a missing row here that nothing arrives.
|
|
212
|
+
|
|
183
213
|
## Props (verbatim from schema.ts)
|
|
184
214
|
|
|
185
215
|
### Core
|
|
@@ -379,6 +409,12 @@ export type TextProps = TextContent & {
|
|
|
379
409
|
* the current left-to-right behavior. Both renderers honor it (parity). */
|
|
380
410
|
textDirection?: "auto" | "ltr" | "rtl";
|
|
381
411
|
decoration?: "underline" | "strikethrough";
|
|
412
|
+
/** EXTRA SPACE BETWEEN LINES, in points/px — added ON TOP of the line height the `style`
|
|
413
|
+
* token already sets. It is NOT a multiple: `lineSpacing: 6` means six points of extra
|
|
414
|
+
* leading, not six times the font size, and every renderer agrees on that. To
|
|
415
|
+
* change the line height as a ratio of the font size, set the typography token's `line`
|
|
416
|
+
* instead; that is where a body style's 1.4/1.7 lives. Absent/0 = the token's own line
|
|
417
|
+
* height, which is the right answer for almost every screen. */
|
|
382
418
|
lineSpacing?: number;
|
|
383
419
|
/** Per-item gate (usually an `$item.` field pre-substituted per row): when it
|
|
384
420
|
* resolves empty, the text collapses to zero size instead of taking layout. */
|
|
@@ -519,6 +555,21 @@ export interface TextFieldProps {
|
|
|
519
555
|
}
|
|
520
556
|
```
|
|
521
557
|
|
|
558
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
559
|
+
|
|
560
|
+
| callback | key | type |
|
|
561
|
+
|---|---|---|
|
|
562
|
+
| `onChange` | `value` | string |
|
|
563
|
+
| `onSubmit` | `value` | string |
|
|
564
|
+
|
|
565
|
+
> `onChange` — The typed text, clamped to maxLength by the renderer.
|
|
566
|
+
|
|
567
|
+
> ⚠️ **`onChange` on ios + android + web — ALSO sends:** additionally injects `fieldId` when the text field is inside a Form, so one worker action can serve several fields. Additive, not conflicting, and shipped bundles already duck-type it. Every arm guards on the field actually being registered in a Form, so a standalone TextField still sends no `fieldId`. Still a divergence rather than a promoted contract key because RN does not send it and the contract does not require it.
|
|
568
|
+
|
|
569
|
+
> `onSubmit` — The field's current text at return-key time.
|
|
570
|
+
|
|
571
|
+
> ⚠️ **`onSubmit` on ios + android + web — ALSO sends:** additionally injects `fieldId` when the text field is inside a Form, so one worker action can serve several fields. Additive, not conflicting, and shipped bundles already duck-type it. Every arm guards on the field actually being registered in a Form, so a standalone TextField still sends no `fieldId`. Still a divergence rather than a promoted contract key because RN does not send it and the contract does not require it.
|
|
572
|
+
|
|
522
573
|
#### Toggle
|
|
523
574
|
|
|
524
575
|
```ts
|
|
@@ -543,6 +594,16 @@ export interface ToggleProps {
|
|
|
543
594
|
}
|
|
544
595
|
```
|
|
545
596
|
|
|
597
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
598
|
+
|
|
599
|
+
| callback | key | type |
|
|
600
|
+
|---|---|---|
|
|
601
|
+
| `onChange` | `value` | boolean |
|
|
602
|
+
|
|
603
|
+
> `onChange` — The NEXT state, not the previous one.
|
|
604
|
+
|
|
605
|
+
> ⚠️ **`onChange` on ios — ALSO sends:** additionally injects `fieldId` when the control is inside a Form — via bindingForBool, for a Toggle nested in a FormField.
|
|
606
|
+
|
|
546
607
|
#### Stepper
|
|
547
608
|
|
|
548
609
|
```ts
|
|
@@ -556,6 +617,16 @@ export interface StepperProps {
|
|
|
556
617
|
}
|
|
557
618
|
```
|
|
558
619
|
|
|
620
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
621
|
+
|
|
622
|
+
| callback | key | type |
|
|
623
|
+
|---|---|---|
|
|
624
|
+
| `onChange` | `value` | int |
|
|
625
|
+
|
|
626
|
+
> `onChange` — The clamped next value. A no-change step must not dispatch.
|
|
627
|
+
|
|
628
|
+
> ⚠️ **`onChange` on web + rn — DIVERGES:** mirrors the value into `params` as a NUMBER. Violates rule 2 — `Action.params` is `map<string,string>`. Harmless through the JS hosts, wrong on the wire.
|
|
629
|
+
|
|
559
630
|
#### Avatar
|
|
560
631
|
|
|
561
632
|
```ts
|
|
@@ -712,6 +783,16 @@ export interface PickerProps {
|
|
|
712
783
|
|
|
713
784
|
> ⚠️ **Implemented, but these props are inert on ios:** `optionsPath`, `placeholder` — `optionsPath` does not bind options; `placeholder` is not shown.
|
|
714
785
|
|
|
786
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
787
|
+
|
|
788
|
+
| callback | key | type |
|
|
789
|
+
|---|---|---|
|
|
790
|
+
| `onChange` | `selectedId` | string |
|
|
791
|
+
|
|
792
|
+
> `onChange` — The chosen option's id — an enum the reducer switches on, never an index.
|
|
793
|
+
|
|
794
|
+
> ⚠️ **`onChange` on ios — DIVERGES:** inside a FormField, the non-text kinds store into the form bag and RETURN without dispatching — the renderer's own code. A formField({kind:'picker'}) onChange is a dead action on iOS while every other arm fires it.
|
|
795
|
+
|
|
715
796
|
#### DatePicker
|
|
716
797
|
|
|
717
798
|
```ts
|
|
@@ -728,6 +809,20 @@ export interface DatePickerProps {
|
|
|
728
809
|
|
|
729
810
|
> ⚠️ **Implemented, but these props are inert on ios:** `mode`, `minUnix`, `maxUnix`, `valuePath` — The picker itself renders as a native date wheel — these four props are inert: `mode: "time"` still renders a date wheel; `minUnix`/`maxUnix` do not clamp; `valuePath` does not bind.
|
|
730
811
|
|
|
812
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
813
|
+
|
|
814
|
+
| callback | key | type |
|
|
815
|
+
|---|---|---|
|
|
816
|
+
| `onChange` | `value` | unix-seconds-string |
|
|
817
|
+
|
|
818
|
+
> `onChange` — Unix SECONDS, string-encoded so the params mirror stays legal. iOS ships `valueUnix` as an int instead; RN ships nothing. The normative key is `value` because that is what three of four arms already use for every other scalar control.
|
|
819
|
+
|
|
820
|
+
> ⚠️ **`onChange` on ios — DIVERGES:** sends `valueUnix` as an int instead of the contract's `value`. Only web conforms. This is the widest split in the vocabulary and the clearest argument for the file.
|
|
821
|
+
|
|
822
|
+
> ⚠️ **`onChange` on rn — DIVERGES:** dispatches the bare action with no date at all.
|
|
823
|
+
|
|
824
|
+
> ⚠️ **`onChange` on ios — DIVERGES:** inside a FormField, the non-text kinds store into the form bag and RETURN without dispatching — the renderer's own code. A formField({kind:'picker'}) onChange is a dead action on iOS while every other arm fires it.
|
|
825
|
+
|
|
731
826
|
### State envelopes
|
|
732
827
|
|
|
733
828
|
#### StatefulSection
|
|
@@ -793,6 +888,17 @@ export interface SearchFieldProps {
|
|
|
793
888
|
}
|
|
794
889
|
```
|
|
795
890
|
|
|
891
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
892
|
+
|
|
893
|
+
| callback | key | type |
|
|
894
|
+
|---|---|---|
|
|
895
|
+
| `onChange` | `value` | string |
|
|
896
|
+
| `onSubmit` | `value` | string |
|
|
897
|
+
|
|
898
|
+
> `onChange` — Debounced by `debounceMs` before dispatch.
|
|
899
|
+
|
|
900
|
+
> `onSubmit` — These two rows share a control and key, so they are NOT independently gated: a payload observation cannot say which callback produced it, and a helper-mediated dispatch does not name the callback at the write site at all. The gate proves the callback is still referenced in the component that dispatches, not that this callback carries the payload.
|
|
901
|
+
|
|
796
902
|
#### FilterChips
|
|
797
903
|
|
|
798
904
|
```ts
|
|
@@ -807,6 +913,16 @@ export interface FilterChipsProps {
|
|
|
807
913
|
}
|
|
808
914
|
```
|
|
809
915
|
|
|
916
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
917
|
+
|
|
918
|
+
| callback | key | type |
|
|
919
|
+
|---|---|---|
|
|
920
|
+
| `onChange` | `selectedIds` | string-array |
|
|
921
|
+
|
|
922
|
+
> `onChange` — The full selection AFTER the toggle, not the chip that moved.
|
|
923
|
+
|
|
924
|
+
> ⚠️ **`onChange` on rn — DIVERGES:** mirrors `selectedIds` into `params` as an ARRAY. Rule-2 violation.
|
|
925
|
+
|
|
810
926
|
### Navigation primitives
|
|
811
927
|
|
|
812
928
|
#### Tabs
|
|
@@ -827,6 +943,12 @@ export interface TabsProps {
|
|
|
827
943
|
|
|
828
944
|
> ⚠️ **Implemented, but these props are inert on ios:** `style` — The tab bar itself renders — only `style` is inert: `swipe` still renders as top tabs.
|
|
829
945
|
|
|
946
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
947
|
+
|
|
948
|
+
| callback | key | type |
|
|
949
|
+
|---|---|---|
|
|
950
|
+
| `onChange` | `selectedId` | string |
|
|
951
|
+
|
|
830
952
|
#### SegmentedControl
|
|
831
953
|
|
|
832
954
|
```ts
|
|
@@ -840,6 +962,12 @@ export interface SegmentedControlProps {
|
|
|
840
962
|
}
|
|
841
963
|
```
|
|
842
964
|
|
|
965
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
966
|
+
|
|
967
|
+
| callback | key | type |
|
|
968
|
+
|---|---|---|
|
|
969
|
+
| `onChange` | `selectedId` | string |
|
|
970
|
+
|
|
843
971
|
#### Carousel
|
|
844
972
|
|
|
845
973
|
```ts
|
|
@@ -1056,6 +1184,20 @@ export interface SliderProps {
|
|
|
1056
1184
|
|
|
1057
1185
|
> ⚠️ **Implemented, but these props are inert on ios:** `debounceMs` — `debounceMs` does not throttle the onChange stream.
|
|
1058
1186
|
|
|
1187
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
1188
|
+
|
|
1189
|
+
| callback | key | type |
|
|
1190
|
+
|---|---|---|
|
|
1191
|
+
| `onChange` | `value` | double |
|
|
1192
|
+
|
|
1193
|
+
> `onChange` — Range mode additionally sends `upperValue`.
|
|
1194
|
+
|
|
1195
|
+
> ⚠️ **`onChange` on web — DIVERGES:** dispatches the bare action — the renderer's own code — with no injected value.
|
|
1196
|
+
|
|
1197
|
+
> ⚠️ **`onChange` on rn — DIVERGES:** renders a static visual and never dispatches at all. RN Slider is unimplemented rather than divergent; listed so the gap is counted, not hidden.
|
|
1198
|
+
|
|
1199
|
+
> ⚠️ **`onChange` on ios + android — ALSO sends:** range mode additionally sends `upperValue` beside `value`. Additive, and the contract's Slider note already describes it. Same problem as groupId: allowed by a hard-coded list rather than declared.
|
|
1200
|
+
|
|
1059
1201
|
#### SelectionControl
|
|
1060
1202
|
|
|
1061
1203
|
```ts
|
|
@@ -1074,6 +1216,20 @@ export interface SelectionControlProps {
|
|
|
1074
1216
|
}
|
|
1075
1217
|
```
|
|
1076
1218
|
|
|
1219
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
1220
|
+
|
|
1221
|
+
| callback | key | type |
|
|
1222
|
+
|---|---|---|
|
|
1223
|
+
| `onChange` | `value` | boolean |
|
|
1224
|
+
|
|
1225
|
+
> `onChange` — The next checked state. iOS additionally sends `groupId` for radio groups.
|
|
1226
|
+
|
|
1227
|
+
> ⚠️ **`onChange` on web — DIVERGES:** dispatches the bare action — the renderer's own code — with no injected value.
|
|
1228
|
+
|
|
1229
|
+
> ⚠️ **`onChange` on rn — DIVERGES:** mirrors the value into `params` as a BOOLEAN.
|
|
1230
|
+
|
|
1231
|
+
> ⚠️ **`onChange` on ios — ALSO sends:** additionally sends `groupId` so a radio group can identify which set changed. Additive, not conflicting. It was previously hard-coded as an allowed key in the gate, which put it outside the contract — the one place this PR claims is the single source of truth.
|
|
1232
|
+
|
|
1077
1233
|
#### ActivityIndicator
|
|
1078
1234
|
|
|
1079
1235
|
```ts
|
|
@@ -1200,6 +1356,16 @@ export interface ChipsInputProps {
|
|
|
1200
1356
|
|
|
1201
1357
|
> ⚠️ **Implemented, but these props are inert on ios:** `onAdd` — `onAdd` never dispatches.
|
|
1202
1358
|
|
|
1359
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
1360
|
+
|
|
1361
|
+
| callback | key | type |
|
|
1362
|
+
|---|---|---|
|
|
1363
|
+
| `onRemove` | `value` | string |
|
|
1364
|
+
|
|
1365
|
+
> `onRemove` — The removed chip's value.
|
|
1366
|
+
|
|
1367
|
+
> ⚠️ **`onRemove` on web — DIVERGES:** dispatches the bare action — the renderer's own code — with no injected value.
|
|
1368
|
+
|
|
1203
1369
|
### Structure & disclosure
|
|
1204
1370
|
|
|
1205
1371
|
#### Section
|
|
@@ -1296,6 +1462,20 @@ export interface RatingProps {
|
|
|
1296
1462
|
}
|
|
1297
1463
|
```
|
|
1298
1464
|
|
|
1465
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
1466
|
+
|
|
1467
|
+
| callback | key | type |
|
|
1468
|
+
|---|---|---|
|
|
1469
|
+
| `onChange` | `value` | int |
|
|
1470
|
+
|
|
1471
|
+
> `onChange` — 1-based star index.
|
|
1472
|
+
|
|
1473
|
+
> ⚠️ **`onChange` on web + rn — DIVERGES:** writes the value into `params` ONLY, never `args`. Survives only because the Tier-5 hosts merge params into args. Any consumer reading `args` — which rule 1 says is the payload map — gets nothing.
|
|
1474
|
+
|
|
1475
|
+
> ⚠️ **`onChange` on ios — DIVERGES:** sends `value` as .double where the contract says int.
|
|
1476
|
+
|
|
1477
|
+
> ⚠️ **`onChange` on web + rn — DIVERGES:** stringifies the 1-based index into `params` (`String(i + 1)`) for a control the contract declares `int`. Rule 2 permits a params mirror only for string-encoded values, and Rating is int. The earlier expression heuristic missed it because `String(i + 1)` does not look like a literal — it surfaced only once rule 2 keyed off the declared encoding.
|
|
1478
|
+
|
|
1299
1479
|
#### Chart
|
|
1300
1480
|
|
|
1301
1481
|
```ts
|
|
@@ -1463,6 +1643,16 @@ export interface WheelPickerProps {
|
|
|
1463
1643
|
}
|
|
1464
1644
|
```
|
|
1465
1645
|
|
|
1646
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
1647
|
+
|
|
1648
|
+
| callback | key | type |
|
|
1649
|
+
|---|---|---|
|
|
1650
|
+
| `onChange` | `selectedId` | string |
|
|
1651
|
+
|
|
1652
|
+
> ⚠️ **`onChange` on rn — DIVERGES:** writes `params.value = String(id)` but `args.selectedId = id` — a different key in each map. Conforms on `args` (rule 1) but the params mirror uses the wrong key, so a params-reading consumer sees a key no other arm sends.
|
|
1653
|
+
|
|
1654
|
+
> ⚠️ **`onChange` on web — DIVERGES:** renders a static window of options and never dispatches — the case has no onAction. Unimplemented on web rather than divergent. Surfaced by the missing-site assertion; the other four it reported were blind spots in the scan, now fixed.
|
|
1655
|
+
|
|
1466
1656
|
#### ColorPicker
|
|
1467
1657
|
|
|
1468
1658
|
```ts
|
|
@@ -1475,6 +1665,16 @@ export interface ColorPickerProps {
|
|
|
1475
1665
|
}
|
|
1476
1666
|
```
|
|
1477
1667
|
|
|
1668
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
1669
|
+
|
|
1670
|
+
| callback | key | type |
|
|
1671
|
+
|---|---|---|
|
|
1672
|
+
| `onChange` | `value` | string |
|
|
1673
|
+
|
|
1674
|
+
> `onChange` — Hex, including the leading '#'.
|
|
1675
|
+
|
|
1676
|
+
> ⚠️ **`onChange` on web + rn — DIVERGES:** writes the value into `params` ONLY, never `args`. Survives only because the Tier-5 hosts merge params into args. Any consumer reading `args` — which rule 1 says is the payload map — gets nothing.
|
|
1677
|
+
|
|
1478
1678
|
#### OtpInput
|
|
1479
1679
|
|
|
1480
1680
|
```ts
|
|
@@ -1494,6 +1694,21 @@ export interface OtpInputProps {
|
|
|
1494
1694
|
|
|
1495
1695
|
> ⚠️ **Implemented, but these props are inert on ios:** `onChange`, `onComplete` — Neither callback dispatches.
|
|
1496
1696
|
|
|
1697
|
+
**Dispatches** — see [What a control sends](#what-a-control-sends-action-payloads):
|
|
1698
|
+
|
|
1699
|
+
| callback | key | type |
|
|
1700
|
+
|---|---|---|
|
|
1701
|
+
| `onChange` | `value` | string |
|
|
1702
|
+
| `onComplete` | `value` | string |
|
|
1703
|
+
|
|
1704
|
+
> `onChange` — The assembled code. Only RN dispatches today; web, iOS and Android render the boxes read-only.
|
|
1705
|
+
|
|
1706
|
+
> ⚠️ **`onChange` on web + ios + android — DIVERGES:** renders the digit boxes without wiring onChange — the control dispatches nothing. Unimplemented rather than divergent, but it must be declared: leaving OtpInput out of the contract is what let the gate whitelist RN's payload without checking it.
|
|
1707
|
+
|
|
1708
|
+
> `onComplete` — Fires once the last box is filled, carrying the same assembled code as onChange. Declared separately because it is a second public callback — leaving it out left one outside the contract.
|
|
1709
|
+
|
|
1710
|
+
> ⚠️ **`onComplete` on web + ios + android — DIVERGES:** renders the digit boxes without wiring onChange — the control dispatches nothing. Unimplemented rather than divergent, but it must be declared: leaving OtpInput out of the contract is what let the gate whitelist RN's payload without checking it.
|
|
1711
|
+
|
|
1497
1712
|
### Cross-cutting & media
|
|
1498
1713
|
|
|
1499
1714
|
#### Fab
|
|
@@ -14,6 +14,13 @@ lists) and `apps/family-cart` (cart list). The `examples/dynamic-list.*` pair th
|
|
|
14
14
|
card grids). `Carousel` and `Menu` take `itemsPath` the same way. Do **not** hand-roll
|
|
15
15
|
a "VStack of Cards" — that renders only static items and can't bind live data.
|
|
16
16
|
|
|
17
|
+
**`Grid` is not a `LazyList` with one column.** It shares `itemsPath` and the row
|
|
18
|
+
template, and nothing else: the gesture props in §5 (`onPullToRefresh`, `pagination`)
|
|
19
|
+
and `stickyHeader`/`rowSwipeActions` are declared on `LazyListProps` only. A key `Grid`
|
|
20
|
+
does not declare is **silently dropped** by the native decoders (`ignoreUnknownKeys =
|
|
21
|
+
true`) — `himi validate` catches it and names the declared set, but nothing catches it
|
|
22
|
+
at runtime. If you need pull-to-refresh or load-more, use `LazyList`.
|
|
23
|
+
|
|
17
24
|
## The shape (canonical off-repo)
|
|
18
25
|
|
|
19
26
|
```jsonc
|
|
@@ -70,6 +77,25 @@ including derived presentation fields (`initial` for an avatar letter, `hasImage
|
|
|
70
77
|
booleans, pre-formatted date lines). Vertical-client responses are raw REST JSON —
|
|
71
78
|
map them defensively; typed-looking fields can be absent at runtime.
|
|
72
79
|
|
|
80
|
+
**One carve-out, and it is the useful one: a NESTED REPEATER may bind to the row's own
|
|
81
|
+
array.** "Flat fields" is about *scalar* bindings — `$item.price`, not
|
|
82
|
+
`$item.priceData.formatted.amount`. A `Carousel`/`LazyList`/`Grid` *inside* a row template
|
|
83
|
+
may set `itemsPath: "$item.<field>"` and render that element's own array, with its own
|
|
84
|
+
`$item.` scope one level down. All four renderers resolve it as of #2265; before that fix web
|
|
85
|
+
rendered zero rows silently, which is why older guidance says it cannot be done. So a photo
|
|
86
|
+
carousel per feed row **is** expressible:
|
|
87
|
+
|
|
88
|
+
```jsonc
|
|
89
|
+
{ "id": "photos_$item.id", "body": { "package": "himalaya", "type": "Carousel",
|
|
90
|
+
"props": { "itemsPath": "$item.images", // ← the ROW's array, not a $service: path
|
|
91
|
+
"items": [ { "id": "photo_$item.url", "body": { "package": "himalaya",
|
|
92
|
+
"type": "Image", "props": { "url": "$item.url" } } } ] } } }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`normalize()` still has to put a real array on the row (`images: []`, never `null`), and the
|
|
96
|
+
inner template obeys every rule above — flat scalar fields, no strict-enum bindings. Keep the
|
|
97
|
+
nesting to one level: a carousel of carousels is legal and unreadable.
|
|
98
|
+
|
|
73
99
|
## 3. The descriptor binds the array
|
|
74
100
|
|
|
75
101
|
```jsonc
|
|
@@ -130,8 +156,10 @@ full state-machine idiom: `himi docs recipe-four-state`.
|
|
|
130
156
|
|
|
131
157
|
## 5. Refresh + load-more gestures (RFC 0008)
|
|
132
158
|
|
|
133
|
-
`LazyList`
|
|
134
|
-
|
|
159
|
+
`LazyList` takes two optional gesture props — both are plain action wiring, no new
|
|
160
|
+
worker concepts. **`LazyList` only**: `GridProps` declares `items`, `columns`,
|
|
161
|
+
`columnsMedium`, `columnsExpanded`, `spacing`, `itemsPath` and `staggerMs`, and the
|
|
162
|
+
native decoders drop anything else without a word:
|
|
135
163
|
|
|
136
164
|
```jsonc
|
|
137
165
|
"props": {
|
|
@@ -159,6 +187,21 @@ plain action wiring, no new worker concepts:
|
|
|
159
187
|
- APIs that don't page (or v1 fallbacks without cursors) simply never set
|
|
160
188
|
`nextCursor` — the gesture props are safe to leave in place.
|
|
161
189
|
|
|
190
|
+
## 6. Tapping a row into a detail screen
|
|
191
|
+
|
|
192
|
+
A row usually opens something, and the id space is usually unbounded (every product, every
|
|
193
|
+
listing). **Use ONE canonical detail screen and pass the id as a nav param** — the row's action is
|
|
194
|
+
`{ "actionId": "himi.open", "params": { "screenId": "property_detail", "id": "$item.id" } }`, and
|
|
195
|
+
the detail worker reads `himalaya.input.id`.
|
|
196
|
+
|
|
197
|
+
The alternative, a **templated route** (`screens.templated` with a `pattern`), is for a *bounded*
|
|
198
|
+
catalog and nothing else. It resolves live for any id while you are developing, which is what makes it
|
|
199
|
+
look like the general answer — but a production OTA release serves only `screens.exact`, so the
|
|
200
|
+
build materializes one screen per id from the route's `seedIds` and a record created after that
|
|
201
|
+
push is simply not in the release. Reach for it when the set is small and known (a handful of
|
|
202
|
+
categories); reach for the canonical screen whenever the ids come from a live collection.
|
|
203
|
+
Mechanics and the prod caveat in full: `himi docs tier-5-add-a-screen`.
|
|
204
|
+
|
|
162
205
|
## Gotchas (each of these has cost an agent a full push→drive cycle)
|
|
163
206
|
|
|
164
207
|
- **`itemsPath` must bind to an array.** `himi validate` errors if the bound path's
|
|
@@ -6955,16 +6955,18 @@
|
|
|
6955
6955
|
{
|
|
6956
6956
|
"name": "queryBookings",
|
|
6957
6957
|
"kind": "function",
|
|
6958
|
-
"jsdoc": "",
|
|
6958
|
+
"jsdoc": "/**\n * @scope owner — requires an owner / business identity — a visitor session gets 403.\n *\n * POST /bookings/v2/bookings/query\n */",
|
|
6959
6959
|
"decl": "export function queryBookings(\n req: WixQueryBookingsRequest = {} as WixQueryBookingsRequest,\n opts?: WixCallOptions,\n): Promise<WixQueryBookingsResponse>;",
|
|
6960
|
-
"http": "POST /bookings/v2/bookings/query"
|
|
6960
|
+
"http": "POST /bookings/v2/bookings/query",
|
|
6961
|
+
"scope": "owner"
|
|
6961
6962
|
},
|
|
6962
6963
|
{
|
|
6963
6964
|
"name": "listBookings",
|
|
6964
6965
|
"kind": "function",
|
|
6965
|
-
"jsdoc": "",
|
|
6966
|
+
"jsdoc": "/**\n * @scope owner — requires an owner / business identity — a visitor session gets 403.\n *\n * GET /bookings/v1/bookings\n */",
|
|
6966
6967
|
"decl": "export function listBookings(\n req: WixListBookingsRequest = {} as WixListBookingsRequest,\n opts?: WixCallOptions,\n): Promise<WixListBookingsResponse>;",
|
|
6967
|
-
"http": "GET /bookings/v1/bookings"
|
|
6968
|
+
"http": "GET /bookings/v1/bookings",
|
|
6969
|
+
"scope": "owner"
|
|
6968
6970
|
},
|
|
6969
6971
|
{
|
|
6970
6972
|
"name": "getBooking",
|
|
@@ -10524,10 +10526,17 @@
|
|
|
10524
10526
|
{
|
|
10525
10527
|
"name": "queryDataItems",
|
|
10526
10528
|
"kind": "function",
|
|
10527
|
-
"jsdoc": "/** Query items in a collection — POST /wix-data/v2/items/query.\n *
|
|
10528
|
-
"decl": "export function queryDataItems(\n dataCollectionId: string,\n limit = 50,\n filter?: Record<string, unknown>,\n returnTotalCount = false,\n): Promise<WixQueryDataItemsResponse>;",
|
|
10529
|
+
"jsdoc": "/** Query items in a collection — POST /wix-data/v2/items/query.\n *\n * `filter` is the Wix Data v2 filter object, which the type cannot express (it is\n * `Record<string, unknown>` by construction). A field name maps to a value for\n * equality, or to an operator object:\n *\n * ```ts\n * await queryDataItems(\"Listings\", 20, { city: \"Tel Aviv\" });\n * await queryDataItems(\"Listings\", 20, { price: { $lte: 2_500_000 } });\n * await queryDataItems(\"Listings\", 20, { _id: { $in: [a, b] } });\n * ```\n *\n * `offset` pages: ask for `limit` rows starting at `offset`. Pair it with\n * `returnTotalCount: true`, which fills `pagingMetadata.total` so a caller knows\n * when to stop — it is omitted by default because counting is extra work, and it\n * reports total for OFFSET paging only, which is the mode this function uses.\n *\n * ```ts\n * const first = await queryDataItems(\"Listings\", 50, undefined, true);\n * const total = first.pagingMetadata?.total ?? 0;\n * const rest = await queryDataItems(\"Listings\", 50, undefined, false, 50);\n * ```\n *\n * To read ONE row, use `getDataItem` rather than a page plus a client-side\n * `.find()` — that pattern breaks silently once the collection outgrows `limit`. */",
|
|
10530
|
+
"decl": "export function queryDataItems(\n dataCollectionId: string,\n limit = 50,\n filter?: Record<string, unknown>,\n returnTotalCount = false,\n offset = 0,\n): Promise<WixQueryDataItemsResponse>;",
|
|
10529
10531
|
"http": "POST /wix-data/v2/items/query"
|
|
10530
10532
|
},
|
|
10533
|
+
{
|
|
10534
|
+
"name": "getDataItem",
|
|
10535
|
+
"kind": "function",
|
|
10536
|
+
"jsdoc": "/** Read ONE item by id — GET /wix-data/v2/items/{dataItemId}?dataCollectionId=…\n *\n * Reach for this on a detail screen. Before it existed the only read this package\n * offered was `queryDataItems`, so a detail worker had to fetch a bounded page and\n * find its row client-side:\n *\n * ```ts\n * const res = await queryDataItems(\"Listings\", 50); // ← DON'T\n * const row = (res.dataItems ?? []).find((it) => it.id === id);\n * ```\n *\n * That is correct against a handful of seeded rows and silently wrong once the\n * collection outgrows `limit`. Ask for the row instead:\n *\n * ```ts\n * const { dataItem } = await getDataItem(\"Listings\", id); // ← DO\n * ```\n *\n * The collection id rides the query string rather than a body, because the Wix\n * gateway drops a GET body — and the string is built with `encodeURIComponent`\n * rather than `URLSearchParams`, which the bare Tier-5 worker runtimes (JSCore /\n * Hermes / QuickJS-ng) do not provide. */",
|
|
10537
|
+
"decl": "export function getDataItem(\n dataCollectionId: string,\n dataItemId: string,\n): Promise<{ dataItem?: WixDataItem }>;",
|
|
10538
|
+
"http": "GET /wix-data/v2/items/{…}?dataCollectionId={…}"
|
|
10539
|
+
},
|
|
10531
10540
|
{
|
|
10532
10541
|
"name": "insertDataItem",
|
|
10533
10542
|
"kind": "function",
|
|
@@ -19013,91 +19022,106 @@
|
|
|
19013
19022
|
"name": "MuteStatus",
|
|
19014
19023
|
"kind": "type",
|
|
19015
19024
|
"jsdoc": "/** \"MUTED\" silences the topic on this channel; \"UNMUTED\" delivers it. */",
|
|
19016
|
-
"decl": "export type MuteStatus = \"MUTED\" | \"UNMUTED\";"
|
|
19025
|
+
"decl": "export type MuteStatus = \"MUTED\" | \"UNMUTED\";",
|
|
19026
|
+
"verified": false
|
|
19017
19027
|
},
|
|
19018
19028
|
{
|
|
19019
19029
|
"name": "Channel",
|
|
19020
19030
|
"kind": "type",
|
|
19021
19031
|
"jsdoc": "/** Delivery channel. The mobile push channel value is unconfirmed; \"MOBILE\" is\n * the working default the bundle passes. */",
|
|
19022
|
-
"decl": "export type Channel = \"MOBILE\" | string;"
|
|
19032
|
+
"decl": "export type Channel = \"MOBILE\" | string;",
|
|
19033
|
+
"verified": false
|
|
19023
19034
|
},
|
|
19024
19035
|
{
|
|
19025
19036
|
"name": "PreferenceState",
|
|
19026
19037
|
"kind": "interface",
|
|
19027
19038
|
"jsdoc": "",
|
|
19028
|
-
"decl": "export interface PreferenceState {\n /** \"MUTED\" | \"UNMUTED\" — whether the topic is delivered on this channel. */\n muteStatus?: MuteStatus;\n}"
|
|
19039
|
+
"decl": "export interface PreferenceState {\n /** \"MUTED\" | \"UNMUTED\" — whether the topic is delivered on this channel. */\n muteStatus?: MuteStatus;\n}",
|
|
19040
|
+
"verified": false
|
|
19029
19041
|
},
|
|
19030
19042
|
{
|
|
19031
19043
|
"name": "PreferenceStateData",
|
|
19032
19044
|
"kind": "interface",
|
|
19033
19045
|
"jsdoc": "",
|
|
19034
|
-
"decl": "export interface PreferenceStateData {\n state?: PreferenceState;\n}"
|
|
19046
|
+
"decl": "export interface PreferenceStateData {\n state?: PreferenceState;\n}",
|
|
19047
|
+
"verified": false
|
|
19035
19048
|
},
|
|
19036
19049
|
{
|
|
19037
19050
|
"name": "PreferenceInfo",
|
|
19038
19051
|
"kind": "interface",
|
|
19039
19052
|
"jsdoc": "/** One topic×channel preference for the implicit recipient. */",
|
|
19040
|
-
"decl": "export interface PreferenceInfo {\n /** The notification topic id (matches NotificationTopic.id). */\n topicId: string;\n /** Delivery channel this preference applies to (e.g. \"MOBILE\"). */\n channel?: Channel;\n stateData?: PreferenceStateData;\n}"
|
|
19053
|
+
"decl": "export interface PreferenceInfo {\n /** The notification topic id (matches NotificationTopic.id). */\n topicId: string;\n /** Delivery channel this preference applies to (e.g. \"MOBILE\"). */\n channel?: Channel;\n stateData?: PreferenceStateData;\n}",
|
|
19054
|
+
"verified": false
|
|
19041
19055
|
},
|
|
19042
19056
|
{
|
|
19043
19057
|
"name": "NotificationPreferences",
|
|
19044
19058
|
"kind": "interface",
|
|
19045
19059
|
"jsdoc": "",
|
|
19046
|
-
"decl": "export interface NotificationPreferences {\n preferencesInfo?: PreferenceInfo[];\n}"
|
|
19060
|
+
"decl": "export interface NotificationPreferences {\n preferencesInfo?: PreferenceInfo[];\n}",
|
|
19061
|
+
"verified": false
|
|
19047
19062
|
},
|
|
19048
19063
|
{
|
|
19049
19064
|
"name": "GetMyNotificationPreferencesResponse",
|
|
19050
19065
|
"kind": "interface",
|
|
19051
19066
|
"jsdoc": "",
|
|
19052
|
-
"decl": "export interface GetMyNotificationPreferencesResponse {\n preferences?: NotificationPreferences;\n}"
|
|
19067
|
+
"decl": "export interface GetMyNotificationPreferencesResponse {\n preferences?: NotificationPreferences;\n}",
|
|
19068
|
+
"verified": false
|
|
19053
19069
|
},
|
|
19054
19070
|
{
|
|
19055
19071
|
"name": "NotificationTopic",
|
|
19056
19072
|
"kind": "interface",
|
|
19057
19073
|
"jsdoc": "/** A notification topic — its id is the PreferenceInfo.topicId; displayName is\n * the row label shown in the UI. */",
|
|
19058
|
-
"decl": "export interface NotificationTopic {\n id: string;\n displayName?: string;\n}"
|
|
19074
|
+
"decl": "export interface NotificationTopic {\n id: string;\n displayName?: string;\n}",
|
|
19075
|
+
"verified": false
|
|
19059
19076
|
},
|
|
19060
19077
|
{
|
|
19061
19078
|
"name": "GetNotificationTopicsResponse",
|
|
19062
19079
|
"kind": "interface",
|
|
19063
19080
|
"jsdoc": "",
|
|
19064
|
-
"decl": "export interface GetNotificationTopicsResponse {\n topics?: NotificationTopic[];\n}"
|
|
19081
|
+
"decl": "export interface GetNotificationTopicsResponse {\n topics?: NotificationTopic[];\n}",
|
|
19082
|
+
"verified": false
|
|
19065
19083
|
},
|
|
19066
19084
|
{
|
|
19067
19085
|
"name": "UpsertMyNotificationPreferencesRequest",
|
|
19068
19086
|
"kind": "interface",
|
|
19069
19087
|
"jsdoc": "",
|
|
19070
|
-
"decl": "export interface UpsertMyNotificationPreferencesRequest {\n preferencesInfo: PreferenceInfo[];\n}"
|
|
19088
|
+
"decl": "export interface UpsertMyNotificationPreferencesRequest {\n preferencesInfo: PreferenceInfo[];\n}",
|
|
19089
|
+
"verified": false
|
|
19071
19090
|
},
|
|
19072
19091
|
{
|
|
19073
19092
|
"name": "UpsertMyNotificationPreferencesResponse",
|
|
19074
19093
|
"kind": "interface",
|
|
19075
19094
|
"jsdoc": "",
|
|
19076
|
-
"decl": "export interface UpsertMyNotificationPreferencesResponse {\n preferences?: NotificationPreferences;\n}"
|
|
19095
|
+
"decl": "export interface UpsertMyNotificationPreferencesResponse {\n preferences?: NotificationPreferences;\n}",
|
|
19096
|
+
"verified": false
|
|
19077
19097
|
},
|
|
19078
19098
|
{
|
|
19079
19099
|
"name": "muteStatusFor",
|
|
19080
19100
|
"kind": "function",
|
|
19081
19101
|
"jsdoc": "/** Map a UI \"on\" boolean to a MuteStatus: on ⇒ delivered (\"UNMUTED\"). */",
|
|
19082
|
-
"decl": "export function muteStatusFor(on: boolean): MuteStatus;"
|
|
19102
|
+
"decl": "export function muteStatusFor(on: boolean): MuteStatus;",
|
|
19103
|
+
"verified": false
|
|
19083
19104
|
},
|
|
19084
19105
|
{
|
|
19085
19106
|
"name": "getMyNotificationPreferences",
|
|
19086
19107
|
"kind": "function",
|
|
19087
19108
|
"jsdoc": "/** Get the signed-in member's notification preferences —\n * GET /notifications/v1/preferences-by-implicit-recipient. */",
|
|
19088
|
-
"decl": "export function getMyNotificationPreferences(): Promise<GetMyNotificationPreferencesResponse>;"
|
|
19109
|
+
"decl": "export function getMyNotificationPreferences(): Promise<GetMyNotificationPreferencesResponse>;",
|
|
19110
|
+
"verified": false
|
|
19089
19111
|
},
|
|
19090
19112
|
{
|
|
19091
19113
|
"name": "getNotificationTopics",
|
|
19092
19114
|
"kind": "function",
|
|
19093
19115
|
"jsdoc": "/** List the available notification topics (id + displayName for labels) —\n * GET /notifications/v1/preferences/topics. */",
|
|
19094
|
-
"decl": "export function getNotificationTopics(): Promise<GetNotificationTopicsResponse>;"
|
|
19116
|
+
"decl": "export function getNotificationTopics(): Promise<GetNotificationTopicsResponse>;",
|
|
19117
|
+
"verified": false
|
|
19095
19118
|
},
|
|
19096
19119
|
{
|
|
19097
19120
|
"name": "upsertMyNotificationPreferences",
|
|
19098
19121
|
"kind": "function",
|
|
19099
19122
|
"jsdoc": "/** Upsert one or more of the signed-in member's preferences —\n * POST /notifications/v1/preferences-by-implicit-recipient, body\n * { preferencesInfo }. Pass only the rows that changed. */",
|
|
19100
|
-
"decl": "export function upsertMyNotificationPreferences(\n preferencesInfo: PreferenceInfo[]\n): Promise<UpsertMyNotificationPreferencesResponse>;"
|
|
19123
|
+
"decl": "export function upsertMyNotificationPreferences(\n preferencesInfo: PreferenceInfo[]\n): Promise<UpsertMyNotificationPreferencesResponse>;",
|
|
19124
|
+
"verified": false
|
|
19101
19125
|
}
|
|
19102
19126
|
]
|
|
19103
19127
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.944.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"artifactId": "himalaya-cli"
|
|
65
65
|
}
|
|
66
66
|
},
|
|
67
|
-
"falconPackageHash": "
|
|
67
|
+
"falconPackageHash": "430cfb64da57b0b2bd12c6e873effe559a8b82eb6aaf60bfa1037748"
|
|
68
68
|
}
|