@wix/himalaya-cli 0.1211.0 → 0.1213.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 (41) hide show
  1. package/dist/cli.mjs +20 -21
  2. package/dist/preview-assets.generated.bin +0 -0
  3. package/package.json +2 -2
  4. package/templates/beauty-salon-owner/dev/index.ts +218 -0
  5. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-post/index.ts +63 -16
  6. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-product/index.ts +61 -16
  7. package/templates/community-club-owner/dev/index.ts +327 -0
  8. package/templates/community-club-owner/tier5-src/himi-owner-lite-event/index.ts +59 -14
  9. package/templates/community-club-owner/tier5-src/himi-owner-lite-post/index.ts +63 -16
  10. package/templates/community-club-owner/tier5-src/himi-owner-lite-product/index.ts +61 -16
  11. package/templates/events-meetups-owner/dev/index.ts +218 -0
  12. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-event/index.ts +59 -14
  13. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-post/index.ts +63 -16
  14. package/templates/gym-fitness-owner/dev/index.ts +327 -0
  15. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-event/index.ts +59 -14
  16. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-post/index.ts +63 -16
  17. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-product/index.ts +61 -16
  18. package/templates/nonprofit-cause-owner/dev/index.ts +218 -0
  19. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-event/index.ts +59 -14
  20. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-post/index.ts +63 -16
  21. package/templates/owner-lite/dev/index.ts +327 -0
  22. package/templates/owner-lite/tier5-src/himi-owner-lite-event/index.ts +59 -14
  23. package/templates/owner-lite/tier5-src/himi-owner-lite-post/index.ts +63 -16
  24. package/templates/owner-lite/tier5-src/himi-owner-lite-product/index.ts +61 -16
  25. package/templates/podcast-creator-owner/dev/index.ts +327 -0
  26. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-event/index.ts +59 -14
  27. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-post/index.ts +63 -16
  28. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-product/index.ts +61 -16
  29. package/templates/portfolio-creative-owner/dev/index.ts +218 -0
  30. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-post/index.ts +63 -16
  31. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-product/index.ts +61 -16
  32. package/templates/restaurant-owner/dev/index.ts +327 -0
  33. package/templates/restaurant-owner/tier5-src/himi-owner-lite-event/index.ts +59 -14
  34. package/templates/restaurant-owner/tier5-src/himi-owner-lite-post/index.ts +63 -16
  35. package/templates/restaurant-owner/tier5-src/himi-owner-lite-product/index.ts +61 -16
  36. package/templates/retail-store-owner/dev/index.ts +218 -0
  37. package/templates/retail-store-owner/tier5-src/himi-owner-lite-post/index.ts +63 -16
  38. package/templates/retail-store-owner/tier5-src/himi-owner-lite-product/index.ts +61 -16
  39. package/templates/yoga-studio-owner/dev/index.ts +218 -0
  40. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-event/index.ts +59 -14
  41. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-post/index.ts +63 -16
package/dist/cli.mjs CHANGED
@@ -34745,10 +34745,8 @@ function withTheme(ctx, theme) {
34745
34745
  radius: { ...base.radius ?? {}, ...theme.radius ?? {} },
34746
34746
  spacing: { ...base.spacing ?? {}, ...theme.spacing ?? {} }
34747
34747
  };
34748
- const themed = makeCtx(merged, ctx.scheme, { provider: ctx.provider, onAction: ctx.onAction, intents: ctx.intents, empty: ctx.empty, screenId: ctx.screenId, emitTelemetry: ctx.emitTelemetry, previewSurface: ctx.previewSurface, idiomContext: ctx.idiomContext });
34749
- themed.itemScope = ctx.itemScope;
34750
- if (ctx.rowDivider) themed.rowDivider = true;
34751
- return themed;
34748
+ const tk = makeTokenResolvers(merged, ctx.scheme, ctx.idiomContext);
34749
+ return { ...ctx, ...tk, modStyle: makeModStyle(tk) };
34752
34750
  }
34753
34751
  function ensureAppearKeyframes() {
34754
34752
  if (appearKeyframesInjected || typeof document === "undefined") return;
@@ -37833,7 +37831,8 @@ var init_renderNode = __esm({
37833
37831
  const rawPlaceholder = props.placeholder ?? cfg.placeholder;
37834
37832
  const resolvedPlaceholder = useResolvedScalar(rawPlaceholder, ctx);
37835
37833
  const placeholderIsBinding = isBinding(rawPlaceholder);
37836
- const placeholder2 = rawPlaceholder == null || placeholderIsBinding && resolvedPlaceholder == null ? "Type here\u2026" : placeholderIsBinding ? asTextL10n(resolvedPlaceholder, ctx) : asText2(rawPlaceholder);
37834
+ const placeholder2 = rawPlaceholder == null || placeholderIsBinding && resolvedPlaceholder == null ? "" : placeholderIsBinding ? asTextL10n(resolvedPlaceholder, ctx) : asText2(rawPlaceholder);
37835
+ const placeholderName = placeholder2 || void 0;
37837
37836
  const prefixText = useBoundString(props.prefix, ctx);
37838
37837
  const suffixText = useBoundString(props.suffix, ctx);
37839
37838
  const valueBinding = typeof ctrl === "string" ? ctrl : cfg.value;
@@ -38039,7 +38038,7 @@ var init_renderNode = __esm({
38039
38038
  /* @__PURE__ */ jsxs5("div", { style: composedBox, children: [
38040
38039
  props.leadingIcon && accIcon(props.leadingIcon),
38041
38040
  prefixText && /* @__PURE__ */ jsx8("span", { style: { color: muted, flex: "none" }, children: prefixText }),
38042
- multilineBox ? /* @__PURE__ */ jsx8("textarea", { "data-component-id": componentId, id: fieldDomId, "data-component-type": componentType, ...a11yFwd, ref: inputRef, value: local, onChange: onInput, onKeyDown, onFocus: onFieldFocus, onBlur: onFieldBlur, placeholder: placeholder2, rows: 2, "aria-label": ariaLabelProp ?? placeholder2, "aria-invalid": errored || void 0, "aria-describedby": [errorId, describedByProp].filter(Boolean).join(" ") || void 0, inputMode, autoCapitalize, maxLength, autoCorrect: suggestOff ? "off" : suggestOn ? "on" : void 0, spellCheck: suggestOff ? false : suggestOn ? true : void 0, autoComplete: suggestOff ? "off" : void 0, style: inputBase }) : /* @__PURE__ */ jsx8("input", { "data-component-id": componentId, id: htmlId, "data-component-type": componentType, ...a11yFwd, ref: inputRef, type: secure ? "password" : "text", value: local, onChange: onInput, onKeyDown, onFocus: onFieldFocus, onBlur: onFieldBlur, placeholder: placeholder2, "aria-label": ariaLabelProp ?? placeholder2, "aria-invalid": errored || void 0, "aria-describedby": [errorId, describedByProp].filter(Boolean).join(" ") || void 0, inputMode, autoCapitalize, maxLength, autoCorrect: suggestOff ? "off" : suggestOn ? "on" : void 0, spellCheck: suggestOff ? false : suggestOn ? true : void 0, autoComplete: suggestOff ? "off" : void 0, enterKeyHint, style: inputBase }),
38041
+ multilineBox ? /* @__PURE__ */ jsx8("textarea", { "data-component-id": componentId, id: fieldDomId, "data-component-type": componentType, ...a11yFwd, ref: inputRef, value: local, onChange: onInput, onKeyDown, onFocus: onFieldFocus, onBlur: onFieldBlur, placeholder: placeholder2, rows: 2, "aria-label": ariaLabelProp ?? placeholderName, "aria-invalid": errored || void 0, "aria-describedby": [errorId, describedByProp].filter(Boolean).join(" ") || void 0, inputMode, autoCapitalize, maxLength, autoCorrect: suggestOff ? "off" : suggestOn ? "on" : void 0, spellCheck: suggestOff ? false : suggestOn ? true : void 0, autoComplete: suggestOff ? "off" : void 0, style: inputBase }) : /* @__PURE__ */ jsx8("input", { "data-component-id": componentId, id: htmlId, "data-component-type": componentType, ...a11yFwd, ref: inputRef, type: secure ? "password" : "text", value: local, onChange: onInput, onKeyDown, onFocus: onFieldFocus, onBlur: onFieldBlur, placeholder: placeholder2, "aria-label": ariaLabelProp ?? placeholderName, "aria-invalid": errored || void 0, "aria-describedby": [errorId, describedByProp].filter(Boolean).join(" ") || void 0, inputMode, autoCapitalize, maxLength, autoCorrect: suggestOff ? "off" : suggestOn ? "on" : void 0, spellCheck: suggestOff ? false : suggestOn ? true : void 0, autoComplete: suggestOff ? "off" : void 0, enterKeyHint, style: inputBase }),
38043
38042
  suffixText && /* @__PURE__ */ jsx8("span", { style: { color: muted, flex: "none" }, children: suffixText }),
38044
38043
  props.clearButton && local && /* @__PURE__ */ jsx8("span", { onClick: () => {
38045
38044
  setLocal("");
@@ -62639,21 +62638,21 @@ var init_preview_assets_generated = __esm({
62639
62638
  "../../packages/serve/src/preview-assets.generated.ts"() {
62640
62639
  init_preview_assets_format();
62641
62640
  PREVIEW_ASSET_MANIFEST = [
62642
- { key: "assets/index-CRDm5E9l.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1184658, sha256: "e00b8e526ebcd4dd07db3a03ee7bb81e401575c162498b42bb9aca49d60a6918" },
62643
- { key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 1184666, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
62644
- { key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 1189276, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
62645
- { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1677860, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
62646
- { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1768784, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
62647
- { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1859768, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
62648
- { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1950748, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
62649
- { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 2041620, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
62650
- { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 2132600, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
62651
- { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 2241236, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
62652
- { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 2350320, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
62653
- { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 2459368, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
62654
- { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 2567068, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
62655
- { key: "index.html", contentType: "text/html; charset=utf-8", offset: 2655176, length: 4947, sha256: "094afa56a8e94767674ee8fd7ca3290f67f64930f8e2c6cc874d6d101e35fd7d" },
62656
- { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 2660123, length: 17344, sha256: "d057298d75e7373e5e2c4d11b7d1bcbea88e03af555ba63d97641c78509c58e4" }
62641
+ { key: "assets/index-C7Hu2ZVY.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1184477, sha256: "467121778a7bc69ac19ec6c77f6f2ca7ea80d7fc2915e8981ba0219b5c2fe61d" },
62642
+ { key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 1184485, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
62643
+ { key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 1189095, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
62644
+ { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1677679, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
62645
+ { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1768603, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
62646
+ { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1859587, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
62647
+ { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1950567, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
62648
+ { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 2041439, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
62649
+ { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 2132419, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
62650
+ { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 2241055, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
62651
+ { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 2350139, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
62652
+ { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 2459187, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
62653
+ { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 2566887, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
62654
+ { key: "index.html", contentType: "text/html; charset=utf-8", offset: 2654995, length: 4947, sha256: "b6f3f19b28b680a734bcf73bfb6e3690e478affe9f3c10a3c5c5d8f3e674c9b0" },
62655
+ { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 2659942, length: 17344, sha256: "d057298d75e7373e5e2c4d11b7d1bcbea88e03af555ba63d97641c78509c58e4" }
62657
62656
  ];
62658
62657
  }
62659
62658
  });
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1211.0",
3
+ "version": "0.1213.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": [
@@ -67,5 +67,5 @@
67
67
  "artifactId": "himalaya-cli"
68
68
  }
69
69
  },
70
- "falconPackageHash": "e396c1bc4ed2c787b443d9987dc1a0b6f0fb7ada7b1f8cf2ed2b2439"
70
+ "falconPackageHash": "85a85909eb5f201a49f5414ffcc4d36dbf9a3dcf7acca4a0b3eec160"
71
71
  }
@@ -77509,6 +77509,115 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
77509
77509
  }
77510
77510
  }
77511
77511
  },
77512
+ {
77513
+ "id": "product_delete_confirmation",
77514
+ "body": {
77515
+ "package": "himalaya",
77516
+ "type": "VStack",
77517
+ "props": {
77518
+ "spacing": 10,
77519
+ "alignment": "leading",
77520
+ "children": [
77521
+ {
77522
+ "id": "product_delete_confirmation.title",
77523
+ "body": {
77524
+ "package": "himalaya",
77525
+ "type": "Text",
77526
+ "props": {
77527
+ "text": "Delete this retail line?",
77528
+ "style": "bodyEmphasis"
77529
+ }
77530
+ }
77531
+ },
77532
+ {
77533
+ "id": "product_delete_confirmation.record",
77534
+ "body": {
77535
+ "package": "himalaya",
77536
+ "type": "Text",
77537
+ "props": {
77538
+ "text": "$service:himiOwnerLiteProduct.title",
77539
+ "style": "body",
77540
+ "color": "textSecondary",
77541
+ "maxLines": 2
77542
+ }
77543
+ }
77544
+ },
77545
+ {
77546
+ "id": "",
77547
+ "body": {
77548
+ "package": "himalaya",
77549
+ "type": "Text",
77550
+ "props": {
77551
+ "text": "This cannot be undone.",
77552
+ "style": "footnote",
77553
+ "color": "textSecondary"
77554
+ }
77555
+ }
77556
+ },
77557
+ {
77558
+ "id": "",
77559
+ "body": {
77560
+ "package": "himalaya",
77561
+ "type": "HStack",
77562
+ "props": {
77563
+ "spacing": 8,
77564
+ "children": [
77565
+ {
77566
+ "id": "product_delete_cancel",
77567
+ "body": {
77568
+ "package": "himalaya",
77569
+ "type": "Button",
77570
+ "props": {
77571
+ "title": "Cancel",
77572
+ "style": "secondary",
77573
+ "action": {
77574
+ "actionId": "tier5.himiOwnerLiteProduct.cancelDelete"
77575
+ }
77576
+ }
77577
+ }
77578
+ },
77579
+ {
77580
+ "id": "product_delete_confirm",
77581
+ "body": {
77582
+ "package": "himalaya",
77583
+ "type": "Button",
77584
+ "props": {
77585
+ "title": "Delete",
77586
+ "style": "destructive",
77587
+ "action": {
77588
+ "actionId": "tier5.himiOwnerLiteProduct.confirmDelete"
77589
+ }
77590
+ }
77591
+ }
77592
+ }
77593
+ ]
77594
+ }
77595
+ }
77596
+ }
77597
+ ]
77598
+ }
77599
+ },
77600
+ "modifiers": {
77601
+ "background": {
77602
+ "token": "surfaceElevated"
77603
+ },
77604
+ "border": {
77605
+ "width": 1,
77606
+ "color": {
77607
+ "token": "danger"
77608
+ }
77609
+ },
77610
+ "cornerRadius": 12,
77611
+ "padding": {
77612
+ "leading": 14,
77613
+ "trailing": 14,
77614
+ "top": 14,
77615
+ "bottom": 14
77616
+ },
77617
+ "fillMaxWidth": true,
77618
+ "hiddenPath": "$service:himiOwnerLiteProduct.noDeleteConfirmation"
77619
+ }
77620
+ },
77512
77621
  {
77513
77622
  "id": "",
77514
77623
  "body": {
@@ -79136,6 +79245,115 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
79136
79245
  }
79137
79246
  }
79138
79247
  },
79248
+ {
79249
+ "id": "post_delete_confirmation",
79250
+ "body": {
79251
+ "package": "himalaya",
79252
+ "type": "VStack",
79253
+ "props": {
79254
+ "spacing": 10,
79255
+ "alignment": "leading",
79256
+ "children": [
79257
+ {
79258
+ "id": "post_delete_confirmation.title",
79259
+ "body": {
79260
+ "package": "himalaya",
79261
+ "type": "Text",
79262
+ "props": {
79263
+ "text": "Delete this post?",
79264
+ "style": "bodyEmphasis"
79265
+ }
79266
+ }
79267
+ },
79268
+ {
79269
+ "id": "post_delete_confirmation.record",
79270
+ "body": {
79271
+ "package": "himalaya",
79272
+ "type": "Text",
79273
+ "props": {
79274
+ "text": "$service:himiOwnerLitePost.title",
79275
+ "style": "body",
79276
+ "color": "textSecondary",
79277
+ "maxLines": 2
79278
+ }
79279
+ }
79280
+ },
79281
+ {
79282
+ "id": "",
79283
+ "body": {
79284
+ "package": "himalaya",
79285
+ "type": "Text",
79286
+ "props": {
79287
+ "text": "This cannot be undone.",
79288
+ "style": "footnote",
79289
+ "color": "textSecondary"
79290
+ }
79291
+ }
79292
+ },
79293
+ {
79294
+ "id": "",
79295
+ "body": {
79296
+ "package": "himalaya",
79297
+ "type": "HStack",
79298
+ "props": {
79299
+ "spacing": 8,
79300
+ "children": [
79301
+ {
79302
+ "id": "post_delete_cancel",
79303
+ "body": {
79304
+ "package": "himalaya",
79305
+ "type": "Button",
79306
+ "props": {
79307
+ "title": "Cancel",
79308
+ "style": "secondary",
79309
+ "action": {
79310
+ "actionId": "tier5.himiOwnerLitePost.cancelDelete"
79311
+ }
79312
+ }
79313
+ }
79314
+ },
79315
+ {
79316
+ "id": "post_delete_confirm",
79317
+ "body": {
79318
+ "package": "himalaya",
79319
+ "type": "Button",
79320
+ "props": {
79321
+ "title": "Delete",
79322
+ "style": "destructive",
79323
+ "action": {
79324
+ "actionId": "tier5.himiOwnerLitePost.confirmDelete"
79325
+ }
79326
+ }
79327
+ }
79328
+ }
79329
+ ]
79330
+ }
79331
+ }
79332
+ }
79333
+ ]
79334
+ }
79335
+ },
79336
+ "modifiers": {
79337
+ "background": {
79338
+ "token": "surfaceElevated"
79339
+ },
79340
+ "border": {
79341
+ "width": 1,
79342
+ "color": {
79343
+ "token": "danger"
79344
+ }
79345
+ },
79346
+ "cornerRadius": 12,
79347
+ "padding": {
79348
+ "leading": 14,
79349
+ "trailing": 14,
79350
+ "top": 14,
79351
+ "bottom": 14
79352
+ },
79353
+ "fillMaxWidth": true,
79354
+ "hiddenPath": "$service:himiOwnerLitePost.noDeleteConfirmation"
79355
+ }
79356
+ },
79139
79357
  {
79140
79358
  "id": "",
79141
79359
  "body": {
@@ -80,6 +80,9 @@ interface PostState {
80
80
  /** Non-empty when showing owner-preview-demo sample data (web preview, no owner bridge). */
81
81
  demoNote: string;
82
82
  notDemo: boolean;
83
+ /** #3158 — Delete ARMS a confirmation; only confirmDelete reaches the API. */
84
+ deletePending: boolean;
85
+ noDeleteConfirmation: boolean;
83
86
  }
84
87
 
85
88
  /* eslint-disable @typescript-eslint/no-explicit-any */
@@ -159,6 +162,9 @@ function shape(s: Partial<PostState>): PostState {
159
162
  hideUnpublish: !published || status !== "ready",
160
163
  demoNote: s.demoNote ?? "",
161
164
  notDemo: !s.demoNote,
165
+ // Only a loaded entity can be pending deletion; every other action disarms it (`disarm`).
166
+ deletePending: !!s.deletePending && hasEntity,
167
+ noDeleteConfirmation: !(s.deletePending && hasEntity),
162
168
  };
163
169
  }
164
170
 
@@ -276,18 +282,35 @@ async function refresh(prev: PostState, id: string, actionMessage = ""): Promise
276
282
  });
277
283
  }
278
284
 
285
+ /** #3158 — a confirmed delete in flight. Synchronous and module-level on purpose: two
286
+ * confirmDelete dispatches (a double tap) both start from a state that says "armed", and only a
287
+ * flag set BEFORE the first await stops the second from issuing its own DELETE — whose late 404
288
+ * would otherwise land after, and overwrite, the first one's "deleted". */
289
+ let deleteInFlight = false;
290
+
291
+ /** #3158 — the confirmation describes THIS visit. Never take it from a persisted snapshot, or a
292
+ * reopened record comes back with "Delete this …?" already armed. */
293
+ const DELETE_RUN_KEYS = ["deletePending", "noDeleteConfirmation"] as const;
294
+
295
+ /** #3158 — clear an armed delete confirmation. */
296
+ const disarm = <T extends { deletePending: boolean }>(s: T): T => ({ ...s, deletePending: false });
297
+
279
298
  const svc = defineService<PostState, {
280
299
  load: (s: PostState, arg?: unknown) => Promise<PostState>;
281
300
  retry: (s: PostState) => Promise<PostState>;
282
301
  publish: (s: PostState) => Promise<PostState>;
283
302
  unpublish: (s: PostState) => Promise<PostState>;
284
303
  delete: (s: PostState) => Promise<PostState>;
304
+ cancelDelete: (s: PostState) => Promise<PostState>;
305
+ confirmDelete: (s: PostState) => Promise<PostState | undefined>;
285
306
  /** [rico] #3370 — RichContent's on_link: `{ url }` of the tapped link. */
286
307
  openLink: (s: PostState, arg?: unknown) => Promise<PostState>;
287
308
  }>("himiOwnerLitePost", {
288
309
  state: shape({ status: "loading" }),
310
+ notHydrated: [...DELETE_RUN_KEYS],
289
311
  actions: {
290
- load: async (s, arg) => {
312
+ load: async (s0, arg) => {
313
+ const s = disarm(s0);
291
314
  stashCopy(arg); // absorb the descriptor's onAppear copy-pack param
292
315
  const id = idFrom(arg, s.id) || inputId();
293
316
  if (!id) return shape({ ...s, status: "error", error: copyParam("ownerPost.errorNoId", "no post id") });
@@ -312,7 +335,8 @@ const svc = defineService<PostState, {
312
335
  return shape({ ...s, id, status: "error", error: ownerLoadError(e) });
313
336
  }
314
337
  },
315
- retry: async (s) => {
338
+ retry: async (s0) => {
339
+ const s = disarm(s0);
316
340
  if (!s.id) return shape({ ...s, status: "error", error: copyParam("ownerPost.errorNoId", "no post id") });
317
341
  if (isOwnerPreviewDemo()) {
318
342
  const demo = demoDetail(s, s.id);
@@ -334,7 +358,8 @@ const svc = defineService<PostState, {
334
358
  return shape({ ...s, status: "error", error: ownerLoadError(e) });
335
359
  }
336
360
  },
337
- publish: async (s) => {
361
+ publish: async (s0) => {
362
+ const s = disarm(s0);
338
363
  if (isOwnerPreviewDemo() || s.demoNote) return shape({ ...s, actionMessage: copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) });
339
364
  if (!s.id) return shape({ ...s, actionMessage: copyParam("ownerPost.noIdMessage", "No post id.") });
340
365
  if (s.postStatusRaw === "PUBLISHED") return shape({ ...s, actionMessage: copyParam("ownerPost.alreadyPublished", "Post is already published.") });
@@ -352,7 +377,8 @@ const svc = defineService<PostState, {
352
377
  return shape({ ...s, actionMessage: ownerLoadError(e) });
353
378
  }
354
379
  },
355
- unpublish: async (s) => {
380
+ unpublish: async (s0) => {
381
+ const s = disarm(s0);
356
382
  if (isOwnerPreviewDemo() || s.demoNote) return shape({ ...s, actionMessage: copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) });
357
383
  if (!s.id) return shape({ ...s, actionMessage: copyParam("ownerPost.noIdMessage", "No post id.") });
358
384
  if (s.postStatusRaw !== "PUBLISHED" && s.postStatusRaw !== "SCHEDULED") {
@@ -372,20 +398,35 @@ const svc = defineService<PostState, {
372
398
  return shape({ ...s, actionMessage: ownerLoadError(e) });
373
399
  }
374
400
  },
375
- delete: async (s) => {
376
- if (isOwnerPreviewDemo() || s.demoNote) return shape({ ...s, actionMessage: copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) });
377
- if (!s.id) return shape({ ...s, actionMessage: copyParam("ownerPost.noIdMessage", "No post id.") });
378
- // Optimistic local delete — the list drops the row immediately.
379
- await cacheDrop(s.id);
401
+ // #3158 — destructive, so two steps. `delete` (the Manage card's Delete button)
402
+ // only ARMS the inline confirmation, which names the record and says it cannot
403
+ // be undone; `cancelDelete` disarms it; only `confirmDelete` deletes. Anything
404
+ // that dispatches `delete` directly therefore still asks first.
405
+ delete: async (s) => shape({ ...s, deletePending: true, actionMessage: "" }),
406
+ cancelDelete: async (s) => shape({ ...s, deletePending: false }),
407
+ confirmDelete: async (s0) => {
408
+ // Nothing armed (a stray dispatch, a rehydrated snapshot) or a delete already running
409
+ // (a second tap): ignore it — `undefined` leaves the state exactly as it is.
410
+ if (!s0.deletePending || deleteInFlight) return undefined;
411
+ deleteInFlight = true;
380
412
  try {
381
- await deleteDraftPost(s.id);
382
- return shape({ ...s, status: "deleted", title: "", emptyText: copyParam("ownerPost.deletedEmpty", "Post deleted."), actionMessage: "" });
383
- } catch (e) {
384
- if (shouldQueueOwnerWrite(e)) {
385
- await queueWrite("tier5.himiOwnerLitePost.delete", { id: s.id });
386
- return shape({ ...s, status: "deleted", title: "", emptyText: copyParam("ownerPost.deletedEmpty", "Post deleted."), actionMessage: copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) });
413
+ const s = disarm(s0);
414
+ if (isOwnerPreviewDemo() || s.demoNote) return shape({ ...s, actionMessage: copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) });
415
+ if (!s.id) return shape({ ...s, actionMessage: copyParam("ownerPost.noIdMessage", "No post id.") });
416
+ // Optimistic local delete — the list drops the row immediately.
417
+ await cacheDrop(s.id);
418
+ try {
419
+ await deleteDraftPost(s.id);
420
+ return shape({ ...s, status: "deleted", title: "", emptyText: copyParam("ownerPost.deletedEmpty", "Post deleted."), actionMessage: "" });
421
+ } catch (e) {
422
+ if (shouldQueueOwnerWrite(e)) {
423
+ await queueWrite("tier5.himiOwnerLitePost.delete", { id: s.id });
424
+ return shape({ ...s, status: "deleted", title: "", emptyText: copyParam("ownerPost.deletedEmpty", "Post deleted."), actionMessage: copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) });
425
+ }
426
+ return shape({ ...s, actionMessage: ownerLoadError(e) });
387
427
  }
388
- return shape({ ...s, actionMessage: ownerLoadError(e) });
428
+ } finally {
429
+ deleteInFlight = false;
389
430
  }
390
431
  },
391
432
  // Only http(s), mailto and tel links reach open_url; a refused link, or one nothing opened, says so, and
@@ -397,4 +438,10 @@ const svc = defineService<PostState, {
397
438
  },
398
439
  });
399
440
 
441
+ // The same reset on a runtime from before `notHydrated` (an older binary on a new bundle).
442
+ if ((globalThis as { himalaya?: { hydrationOptOut?: unknown } }).himalaya?.hydrationOptOut !== true) {
443
+ const booted = svc.getState?.() as unknown as Record<string, unknown> | undefined;
444
+ if (booted && typeof booted === "object") Object.assign(booted, { deletePending: false, noDeleteConfirmation: true });
445
+ }
446
+
400
447
  export { svc };
@@ -59,6 +59,9 @@ interface ProductState {
59
59
  /** Non-empty when showing owner-preview-demo sample data (web preview, no owner bridge). */
60
60
  demoNote: string;
61
61
  notDemo: boolean;
62
+ /** #3158 — Delete ARMS a confirmation; only confirmDelete reaches the API. */
63
+ deletePending: boolean;
64
+ noDeleteConfirmation: boolean;
62
65
  }
63
66
 
64
67
  /* eslint-disable @typescript-eslint/no-explicit-any */
@@ -143,6 +146,9 @@ function shape(s: Partial<ProductState>): ProductState {
143
146
  hideHide: !visible || status !== "ready",
144
147
  demoNote: s.demoNote ?? "",
145
148
  notDemo: !s.demoNote,
149
+ // Only a loaded entity can be pending deletion; every other action disarms it (`disarm`).
150
+ deletePending: !!s.deletePending && hasEntity,
151
+ noDeleteConfirmation: !(s.deletePending && hasEntity),
146
152
  };
147
153
  }
148
154
 
@@ -265,16 +271,33 @@ async function setVisibility(s: ProductState, visible: boolean, msg: string): Pr
265
271
  }
266
272
  }
267
273
 
274
+ /** #3158 — a confirmed delete in flight. Synchronous and module-level on purpose: two
275
+ * confirmDelete dispatches (a double tap) both start from a state that says "armed", and only a
276
+ * flag set BEFORE the first await stops the second from issuing its own DELETE — whose late 404
277
+ * would otherwise land after, and overwrite, the first one's "deleted". */
278
+ let deleteInFlight = false;
279
+
280
+ /** #3158 — the confirmation describes THIS visit. Never take it from a persisted snapshot, or a
281
+ * reopened record comes back with "Delete this …?" already armed. */
282
+ const DELETE_RUN_KEYS = ["deletePending", "noDeleteConfirmation"] as const;
283
+
284
+ /** #3158 — clear an armed delete confirmation. */
285
+ const disarm = <T extends { deletePending: boolean }>(s: T): T => ({ ...s, deletePending: false });
286
+
268
287
  const svc = defineService<ProductState, {
269
288
  load: (s: ProductState, arg?: unknown) => Promise<ProductState>;
270
289
  retry: (s: ProductState) => Promise<ProductState>;
271
290
  show: (s: ProductState) => Promise<ProductState>;
272
291
  hide: (s: ProductState) => Promise<ProductState>;
273
292
  delete: (s: ProductState) => Promise<ProductState>;
293
+ cancelDelete: (s: ProductState) => Promise<ProductState>;
294
+ confirmDelete: (s: ProductState) => Promise<ProductState | undefined>;
274
295
  }>("himiOwnerLiteProduct", {
275
296
  state: shape({ status: "loading" }),
297
+ notHydrated: [...DELETE_RUN_KEYS],
276
298
  actions: {
277
- load: async (s, arg) => {
299
+ load: async (s0, arg) => {
300
+ const s = disarm(s0);
278
301
  stashCopy(arg); // absorb the descriptor's onAppear copy-pack param
279
302
  const id = idFrom(arg, s.id) || inputId();
280
303
  if (!id) return shape({ ...s, status: "error", error: copyParam("ownerProduct.errorNoId", "no product id") });
@@ -297,7 +320,8 @@ const svc = defineService<ProductState, {
297
320
  return shape({ ...s, id, status: "error", error: ownerLoadError(e) });
298
321
  }
299
322
  },
300
- retry: async (s) => {
323
+ retry: async (s0) => {
324
+ const s = disarm(s0);
301
325
  if (!s.id) return shape({ ...s, status: "error", error: copyParam("ownerProduct.errorNoId", "no product id") });
302
326
  if (isOwnerPreviewDemo()) {
303
327
  const demo = demoDetail(s, s.id);
@@ -317,25 +341,46 @@ const svc = defineService<ProductState, {
317
341
  return shape({ ...s, status: "error", error: ownerLoadError(e) });
318
342
  }
319
343
  },
320
- show: async (s) => setVisibility(s, true, copyParam("ownerProduct.shownMessage", "Product is now visible in your store.")),
321
- hide: async (s) => setVisibility(s, false, copyParam("ownerProduct.hiddenMessage", "Product hidden from your store.")),
322
- delete: async (s) => {
323
- if (isOwnerPreviewDemo() || s.demoNote) return shape({ ...s, actionMessage: copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) });
324
- if (!s.id) return shape({ ...s, actionMessage: copyParam("ownerProduct.noIdMessage", "No product id.") });
325
- // Optimistic local delete — the list drops the row immediately.
326
- await cacheDrop(s.id);
344
+ show: async (s0) => { const s = disarm(s0); return setVisibility(s, true, copyParam("ownerProduct.shownMessage", "Product is now visible in your store.")); },
345
+ hide: async (s0) => { const s = disarm(s0); return setVisibility(s, false, copyParam("ownerProduct.hiddenMessage", "Product hidden from your store.")); },
346
+ // #3158 — destructive, so two steps. `delete` (the Manage card's Delete button)
347
+ // only ARMS the inline confirmation, which names the record and says it cannot
348
+ // be undone; `cancelDelete` disarms it; only `confirmDelete` deletes. Anything
349
+ // that dispatches `delete` directly therefore still asks first.
350
+ delete: async (s) => shape({ ...s, deletePending: true, actionMessage: "" }),
351
+ cancelDelete: async (s) => shape({ ...s, deletePending: false }),
352
+ confirmDelete: async (s0) => {
353
+ // Nothing armed (a stray dispatch, a rehydrated snapshot) or a delete already running
354
+ // (a second tap): ignore it — `undefined` leaves the state exactly as it is.
355
+ if (!s0.deletePending || deleteInFlight) return undefined;
356
+ deleteInFlight = true;
327
357
  try {
328
- await deleteProduct(s.id);
329
- return shape({ ...s, status: "deleted", title: "", emptyText: copyParam("ownerProduct.deletedEmpty", "Product deleted."), actionMessage: "" });
330
- } catch (e) {
331
- if (shouldQueueOwnerWrite(e)) {
332
- await queueWrite("tier5.himiOwnerLiteProduct.delete", { id: s.id });
333
- return shape({ ...s, status: "deleted", title: "", emptyText: copyParam("ownerProduct.deletedEmpty", "Product deleted."), actionMessage: copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) });
358
+ const s = disarm(s0);
359
+ if (isOwnerPreviewDemo() || s.demoNote) return shape({ ...s, actionMessage: copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) });
360
+ if (!s.id) return shape({ ...s, actionMessage: copyParam("ownerProduct.noIdMessage", "No product id.") });
361
+ // Optimistic local delete — the list drops the row immediately.
362
+ await cacheDrop(s.id);
363
+ try {
364
+ await deleteProduct(s.id);
365
+ return shape({ ...s, status: "deleted", title: "", emptyText: copyParam("ownerProduct.deletedEmpty", "Product deleted."), actionMessage: "" });
366
+ } catch (e) {
367
+ if (shouldQueueOwnerWrite(e)) {
368
+ await queueWrite("tier5.himiOwnerLiteProduct.delete", { id: s.id });
369
+ return shape({ ...s, status: "deleted", title: "", emptyText: copyParam("ownerProduct.deletedEmpty", "Product deleted."), actionMessage: copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) });
370
+ }
371
+ return shape({ ...s, actionMessage: ownerLoadError(e) });
334
372
  }
335
- return shape({ ...s, actionMessage: ownerLoadError(e) });
373
+ } finally {
374
+ deleteInFlight = false;
336
375
  }
337
376
  },
338
377
  },
339
378
  });
340
379
 
380
+ // The same reset on a runtime from before `notHydrated` (an older binary on a new bundle).
381
+ if ((globalThis as { himalaya?: { hydrationOptOut?: unknown } }).himalaya?.hydrationOptOut !== true) {
382
+ const booted = svc.getState?.() as unknown as Record<string, unknown> | undefined;
383
+ if (booted && typeof booted === "object") Object.assign(booted, { deletePending: false, noDeleteConfirmation: true });
384
+ }
385
+
341
386
  export { svc };