@shapio/cms 0.5.5 → 0.5.6

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 (156) hide show
  1. package/dist/admin/assets/{AssetTile-CaYPqR_F.js → AssetTile-_qRYsivK.js} +2 -2
  2. package/dist/admin/assets/{AssetTile-CaYPqR_F.js.map → AssetTile-_qRYsivK.js.map} +1 -1
  3. package/dist/admin/assets/{AssistError-drmpXSbS.js → AssistError-CMXQWiQo.js} +2 -2
  4. package/dist/admin/assets/{AssistError-drmpXSbS.js.map → AssistError-CMXQWiQo.js.map} +1 -1
  5. package/dist/admin/assets/{BlockMenuItems-D-jZ0oaU.js → BlockMenuItems-WIrbyv1a.js} +2 -2
  6. package/dist/admin/assets/{BlockMenuItems-D-jZ0oaU.js.map → BlockMenuItems-WIrbyv1a.js.map} +1 -1
  7. package/dist/admin/assets/{Body-Gn_z2KPN.js → Body-BYc1IVsQ.js} +2 -2
  8. package/dist/admin/assets/{Body-Gn_z2KPN.js.map → Body-BYc1IVsQ.js.map} +1 -1
  9. package/dist/admin/assets/Builder-CwHpRhZN.js +2 -0
  10. package/dist/admin/assets/Builder-CwHpRhZN.js.map +1 -0
  11. package/dist/admin/assets/{CodeEditor-CzRU6och.js → CodeEditor-NMvrWgxT.js} +2 -2
  12. package/dist/admin/assets/{CodeEditor-CzRU6och.js.map → CodeEditor-NMvrWgxT.js.map} +1 -1
  13. package/dist/admin/assets/{ConfirmDialog-DZRJfdvH.js → ConfirmDialog-Rd6WDt6q.js} +2 -2
  14. package/dist/admin/assets/{ConfirmDialog-DZRJfdvH.js.map → ConfirmDialog-Rd6WDt6q.js.map} +1 -1
  15. package/dist/admin/assets/{CopyButton-h4HYhnYp.js → CopyButton-B0RuxynJ.js} +2 -2
  16. package/dist/admin/assets/{CopyButton-h4HYhnYp.js.map → CopyButton-B0RuxynJ.js.map} +1 -1
  17. package/dist/admin/assets/{CursorPager-H4SpVYw7.js → CursorPager-CQZsKNxR.js} +2 -2
  18. package/dist/admin/assets/{CursorPager-H4SpVYw7.js.map → CursorPager-CQZsKNxR.js.map} +1 -1
  19. package/dist/admin/assets/{FocalPoint-CSeKI4Iw.js → FocalPoint-BYu2fOTb.js} +2 -2
  20. package/dist/admin/assets/{FocalPoint-CSeKI4Iw.js.map → FocalPoint-BYu2fOTb.js.map} +1 -1
  21. package/dist/admin/assets/{Form-DF_YmR1G.js → Form-CiZUsLPp.js} +2 -2
  22. package/dist/admin/assets/{Form-DF_YmR1G.js.map → Form-CiZUsLPp.js.map} +1 -1
  23. package/dist/admin/assets/{FormCheckboxGroup-V3IKrvzc.js → FormCheckboxGroup-Bz8KERs1.js} +2 -2
  24. package/dist/admin/assets/{FormCheckboxGroup-V3IKrvzc.js.map → FormCheckboxGroup-Bz8KERs1.js.map} +1 -1
  25. package/dist/admin/assets/{FormRadioGroup-DIv-MYgn.js → FormRadioGroup-c-wyx7dq.js} +2 -2
  26. package/dist/admin/assets/{FormRadioGroup-DIv-MYgn.js.map → FormRadioGroup-c-wyx7dq.js.map} +1 -1
  27. package/dist/admin/assets/{FormSelectField-CUhaPIMY.js → FormSelectField-ijG9qPpb.js} +2 -2
  28. package/dist/admin/assets/{FormSelectField-CUhaPIMY.js.map → FormSelectField-ijG9qPpb.js.map} +1 -1
  29. package/dist/admin/assets/{FormSwitchField-DW8ysyk_.js → FormSwitchField-Bp3hNpeP.js} +2 -2
  30. package/dist/admin/assets/{FormSwitchField-DW8ysyk_.js.map → FormSwitchField-Bp3hNpeP.js.map} +1 -1
  31. package/dist/admin/assets/{FormTextareaField-DbqZ-MwI.js → FormTextareaField-BSKMqHcW.js} +2 -2
  32. package/dist/admin/assets/{FormTextareaField-DbqZ-MwI.js.map → FormTextareaField-BSKMqHcW.js.map} +1 -1
  33. package/dist/admin/assets/{HintedLabel-BlLtqVVz.js → HintedLabel-BrLH4NQW.js} +2 -2
  34. package/dist/admin/assets/{HintedLabel-BlLtqVVz.js.map → HintedLabel-BrLH4NQW.js.map} +1 -1
  35. package/dist/admin/assets/{InfoHint-bYMd_t0J.js → InfoHint-Dyzyf59c.js} +2 -2
  36. package/dist/admin/assets/{InfoHint-bYMd_t0J.js.map → InfoHint-Dyzyf59c.js.map} +1 -1
  37. package/dist/admin/assets/{InsertMenuItem-D2HGERzb.js → InsertMenuItem-BvRDuXtd.js} +2 -2
  38. package/dist/admin/assets/{InsertMenuItem-D2HGERzb.js.map → InsertMenuItem-BvRDuXtd.js.map} +1 -1
  39. package/dist/admin/assets/{Match-GDx_orOH.js → Match-Bixf1ygj.js} +2 -2
  40. package/dist/admin/assets/{Match-GDx_orOH.js.map → Match-Bixf1ygj.js.map} +1 -1
  41. package/dist/admin/assets/{QueryView-UBO-U5Wo.js → QueryView--_vvV7dC.js} +2 -2
  42. package/dist/admin/assets/{QueryView-UBO-U5Wo.js.map → QueryView--_vvV7dC.js.map} +1 -1
  43. package/dist/admin/assets/{RadioTile-CJbIIV8t.js → RadioTile-BCp6auUz.js} +2 -2
  44. package/dist/admin/assets/{RadioTile-CJbIIV8t.js.map → RadioTile-BCp6auUz.js.map} +1 -1
  45. package/dist/admin/assets/{RichTextField-M7HyUhYF.js → RichTextField-fWNjndUc.js} +2 -2
  46. package/dist/admin/assets/{RichTextField-M7HyUhYF.js.map → RichTextField-fWNjndUc.js.map} +1 -1
  47. package/dist/admin/assets/{RowTitle-DoxDM1XL.js → RowTitle-B4CE8tt7.js} +2 -2
  48. package/dist/admin/assets/{RowTitle-DoxDM1XL.js.map → RowTitle-B4CE8tt7.js.map} +1 -1
  49. package/dist/admin/assets/{SecretReveal-kCkLH5jg.js → SecretReveal-BhSqdWqh.js} +2 -2
  50. package/dist/admin/assets/{SecretReveal-kCkLH5jg.js.map → SecretReveal-BhSqdWqh.js.map} +1 -1
  51. package/dist/admin/assets/{SharedGlyph-D1OMHXPf.js → SharedGlyph-71FTypoi.js} +2 -2
  52. package/dist/admin/assets/{SharedGlyph-D1OMHXPf.js.map → SharedGlyph-71FTypoi.js.map} +1 -1
  53. package/dist/admin/assets/StepList-CZJmwy9e.js +2 -0
  54. package/dist/admin/assets/StepList-CZJmwy9e.js.map +1 -0
  55. package/dist/admin/assets/Structure-Dk87778W.js +2 -0
  56. package/dist/admin/assets/{Structure-CO4aJZVP.js.map → Structure-Dk87778W.js.map} +1 -1
  57. package/dist/admin/assets/{SuggestAltButton-CbRUxD5s.js → SuggestAltButton-CxS8IR6m.js} +2 -2
  58. package/dist/admin/assets/{SuggestAltButton-CbRUxD5s.js.map → SuggestAltButton-CxS8IR6m.js.map} +1 -1
  59. package/dist/admin/assets/{Thumbnail-D1XuDElk.js → Thumbnail-BwbCNpgQ.js} +2 -2
  60. package/dist/admin/assets/{Thumbnail-D1XuDElk.js.map → Thumbnail-BwbCNpgQ.js.map} +1 -1
  61. package/dist/admin/assets/{UnsavedChangesGuard-C1n7egF6.js → UnsavedChangesGuard-C6nD55Fn.js} +2 -2
  62. package/dist/admin/assets/{UnsavedChangesGuard-C1n7egF6.js.map → UnsavedChangesGuard-C6nD55Fn.js.map} +1 -1
  63. package/dist/admin/assets/{UserAvatar-Bl32IpG_.js → UserAvatar-D7IbSpsP.js} +2 -2
  64. package/dist/admin/assets/{UserAvatar-Bl32IpG_.js.map → UserAvatar-D7IbSpsP.js.map} +1 -1
  65. package/dist/admin/assets/{badge-ydvfgE8a.js → badge-vLiQczOd.js} +2 -2
  66. package/dist/admin/assets/{badge-ydvfgE8a.js.map → badge-vLiQczOd.js.map} +1 -1
  67. package/dist/admin/assets/{changeSets-DgfCKja3.js → changeSets-D5VevASj.js} +2 -2
  68. package/dist/admin/assets/{changeSets-DgfCKja3.js.map → changeSets-D5VevASj.js.map} +1 -1
  69. package/dist/admin/assets/{constants-esJAnNTh.js → constants-CKGh8uwT.js} +2 -2
  70. package/dist/admin/assets/{constants-esJAnNTh.js.map → constants-CKGh8uwT.js.map} +1 -1
  71. package/dist/admin/assets/{content-DsMSB6Wb.js → content-Cbavyq0x.js} +3 -3
  72. package/dist/admin/assets/{content-DsMSB6Wb.js.map → content-Cbavyq0x.js.map} +1 -1
  73. package/dist/admin/assets/{contentTypes-C-AKiYu1.js → contentTypes-DzQ_0v36.js} +2 -2
  74. package/dist/admin/assets/{contentTypes-C-AKiYu1.js.map → contentTypes-DzQ_0v36.js.map} +1 -1
  75. package/dist/admin/assets/{develop-DL-2W9jv.js → develop-BDqMOEql.js} +2 -2
  76. package/dist/admin/assets/{develop-DL-2W9jv.js.map → develop-BDqMOEql.js.map} +1 -1
  77. package/dist/admin/assets/{dropdown-menu-C53v9ioW.js → dropdown-menu-CVAnm22s.js} +2 -2
  78. package/dist/admin/assets/{dropdown-menu-C53v9ioW.js.map → dropdown-menu-CVAnm22s.js.map} +1 -1
  79. package/dist/admin/assets/es2015-BKfbx3rz.js +42 -0
  80. package/dist/admin/assets/es2015-BKfbx3rz.js.map +1 -0
  81. package/dist/admin/assets/{field-W1dB_h6d.js → field-Bg-JRgsB.js} +2 -2
  82. package/dist/admin/assets/{field-W1dB_h6d.js.map → field-Bg-JRgsB.js.map} +1 -1
  83. package/dist/admin/assets/{fileRoute-DzWMBrRx.js → fileRoute-DQCI1nMN.js} +2 -2
  84. package/dist/admin/assets/{fileRoute-DzWMBrRx.js.map → fileRoute-DQCI1nMN.js.map} +1 -1
  85. package/dist/admin/assets/{followPlural-D-5ZJqJF.js → followPlural-D0bENI5E.js} +2 -2
  86. package/dist/admin/assets/{followPlural-D-5ZJqJF.js.map → followPlural-D0bENI5E.js.map} +1 -1
  87. package/dist/admin/assets/{inbox-DUqOrFEA.js → inbox-Dfy4YBZ2.js} +2 -2
  88. package/dist/admin/assets/{inbox-DUqOrFEA.js.map → inbox-Dfy4YBZ2.js.map} +1 -1
  89. package/dist/admin/assets/{index-D03RZB7e.js → index-M4TUI1dl.js} +4 -4
  90. package/dist/admin/assets/{index-D03RZB7e.js.map → index-M4TUI1dl.js.map} +1 -1
  91. package/dist/admin/assets/{labels-CHE0gg1n.js → labels-BrwwGWnv.js} +2 -2
  92. package/dist/admin/assets/{labels-CHE0gg1n.js.map → labels-BrwwGWnv.js.map} +1 -1
  93. package/dist/admin/assets/{media-BUUEsWxd.js → media-DBdx-UmR.js} +2 -2
  94. package/dist/admin/assets/{media-BUUEsWxd.js.map → media-DBdx-UmR.js.map} +1 -1
  95. package/dist/admin/assets/{network-Bolr2lmf.js → network-BpbMYp6D.js} +2 -2
  96. package/dist/admin/assets/{network-Bolr2lmf.js.map → network-BpbMYp6D.js.map} +1 -1
  97. package/dist/admin/assets/{publishing-ClNjPLQ9.js → publishing-CpSDO3M7.js} +2 -2
  98. package/dist/admin/assets/{publishing-ClNjPLQ9.js.map → publishing-CpSDO3M7.js.map} +1 -1
  99. package/dist/admin/assets/{radio-group-rFxn7cz2.js → radio-group-DQ3sC1ol.js} +2 -2
  100. package/dist/admin/assets/{radio-group-rFxn7cz2.js.map → radio-group-DQ3sC1ol.js.map} +1 -1
  101. package/dist/admin/assets/{searchSchemas-C4qp-vCa.js → searchSchemas-D4S2ceA0.js} +2 -2
  102. package/dist/admin/assets/{searchSchemas-C4qp-vCa.js.map → searchSchemas-D4S2ceA0.js.map} +1 -1
  103. package/dist/admin/assets/{sections-C7Z6Xd8r.js → sections-Cl1LrzqH.js} +2 -2
  104. package/dist/admin/assets/{sections-C7Z6Xd8r.js.map → sections-Cl1LrzqH.js.map} +1 -1
  105. package/dist/admin/assets/{select-DUhL27UN.js → select-DjCAH45V.js} +2 -2
  106. package/dist/admin/assets/{select-DUhL27UN.js.map → select-DjCAH45V.js.map} +1 -1
  107. package/dist/admin/assets/{seo-l1ZORjtv.js → seo-DJ4k3LtY.js} +2 -2
  108. package/dist/admin/assets/{seo-l1ZORjtv.js.map → seo-DJ4k3LtY.js.map} +1 -1
  109. package/dist/admin/assets/{settings-DgoG3H8C.js → settings-DRZ33PTg.js} +2 -2
  110. package/dist/admin/assets/{settings-DgoG3H8C.js.map → settings-DRZ33PTg.js.map} +1 -1
  111. package/dist/admin/assets/{shapes-BZ87ap5s.js → shapes-BJe3IMuj.js} +5 -5
  112. package/dist/admin/assets/{shapes-BZ87ap5s.js.map → shapes-BJe3IMuj.js.map} +1 -1
  113. package/dist/admin/assets/{skeleton-Dyi_b1wq.js → skeleton-D4eOLKLY.js} +2 -2
  114. package/dist/admin/assets/{skeleton-Dyi_b1wq.js.map → skeleton-D4eOLKLY.js.map} +1 -1
  115. package/dist/admin/assets/src-DUpL-qwG.js +7 -0
  116. package/dist/admin/assets/src-DUpL-qwG.js.map +1 -0
  117. package/dist/admin/assets/{switch-C3dDDUIk.js → switch-B2R13aVU.js} +2 -2
  118. package/dist/admin/assets/{switch-C3dDDUIk.js.map → switch-B2R13aVU.js.map} +1 -1
  119. package/dist/admin/assets/{theme-DPe080iG.js → theme-X-qeg74W.js} +2 -2
  120. package/dist/admin/assets/{theme-DPe080iG.js.map → theme-X-qeg74W.js.map} +1 -1
  121. package/dist/admin/assets/{titles-C5PaMgFJ.js → titles-CLh5ftA2.js} +2 -2
  122. package/dist/admin/assets/{titles-C5PaMgFJ.js.map → titles-CLh5ftA2.js.map} +1 -1
  123. package/dist/admin/assets/{tooltip-BEaZkRPK.js → tooltip-u2epXfJF.js} +2 -2
  124. package/dist/admin/assets/{tooltip-BEaZkRPK.js.map → tooltip-u2epXfJF.js.map} +1 -1
  125. package/dist/admin/assets/{useContentSchema-wLDa2L3f.js → useContentSchema-DaQHlL19.js} +2 -2
  126. package/dist/admin/assets/{useContentSchema-wLDa2L3f.js.map → useContentSchema-DaQHlL19.js.map} +1 -1
  127. package/dist/admin/assets/{useDiscardGuard-WTUINqD5.js → useDiscardGuard-BVJGUCiH.js} +2 -2
  128. package/dist/admin/assets/{useDiscardGuard-WTUINqD5.js.map → useDiscardGuard-BVJGUCiH.js.map} +1 -1
  129. package/dist/admin/assets/{useMediaPickerDialog-CFN9ZKfe.js → useMediaPickerDialog-C23eOHQR.js} +2 -2
  130. package/dist/admin/assets/{useMediaPickerDialog-CFN9ZKfe.js.map → useMediaPickerDialog-C23eOHQR.js.map} +1 -1
  131. package/dist/admin/assets/{useMediaUploader-B42H_CMG.js → useMediaUploader-CTViR0LX.js} +2 -2
  132. package/dist/admin/assets/{useMediaUploader-B42H_CMG.js.map → useMediaUploader-CTViR0LX.js.map} +1 -1
  133. package/dist/admin/assets/{useResolvedScheme-aV0QDPi3.js → useResolvedScheme-Cg8TdO85.js} +2 -2
  134. package/dist/admin/assets/{useResolvedScheme-aV0QDPi3.js.map → useResolvedScheme-Cg8TdO85.js.map} +1 -1
  135. package/dist/admin/assets/{zod-C-k48Hnc.js → zod-D5i60ErJ.js} +2 -2
  136. package/dist/admin/assets/{zod-C-k48Hnc.js.map → zod-D5i60ErJ.js.map} +1 -1
  137. package/dist/admin/index.html +27 -27
  138. package/dist/cli.js +10 -3
  139. package/dist/cli.js.map +1 -1
  140. package/dist/index.d.ts +7 -2
  141. package/dist/index.js +1 -1
  142. package/dist/{s3Adapter-sL1zP4Zl.js → s3Adapter-CtPzkzf0.js} +2 -2
  143. package/dist/{s3Adapter-sL1zP4Zl.js.map → s3Adapter-CtPzkzf0.js.map} +1 -1
  144. package/dist/{worker-DMES6pqh.js → worker-DRCCGGjl.js} +3823 -3719
  145. package/dist/worker-DRCCGGjl.js.map +1 -0
  146. package/package.json +5 -5
  147. package/dist/admin/assets/Builder-DyCcikfS.js +0 -2
  148. package/dist/admin/assets/Builder-DyCcikfS.js.map +0 -1
  149. package/dist/admin/assets/StepList-BIQjDaWQ.js +0 -2
  150. package/dist/admin/assets/StepList-BIQjDaWQ.js.map +0 -1
  151. package/dist/admin/assets/Structure-CO4aJZVP.js +0 -2
  152. package/dist/admin/assets/es2015-DrAA1N2V.js +0 -42
  153. package/dist/admin/assets/es2015-DrAA1N2V.js.map +0 -1
  154. package/dist/admin/assets/src-BcLeD2-K.js +0 -7
  155. package/dist/admin/assets/src-BcLeD2-K.js.map +0 -1
  156. package/dist/worker-DMES6pqh.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"mappings":"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","names":["DEFAULT_SEO_KEYS","isRecord","value","text","resolveSeo","keys","context","output","raw","key","set","next","base","applyTitleTemplate","__iconData","ArrowLeft","createLucideIcon","ChevronsDownUp","RotateCcwClock","__defProp","__name","target","TABS_NAME","createTabsContext","createTabsScope","createContextScope","createRovingFocusGroupScope","useRovingFocusGroupScope","TabsProvider","useTabsContext","Tabs","import_react","__name$2","valueProp","tabsProps","props","direction","useDirection","dir","setValue","useControllableState","onValueChange","defaultValue","import_jsx_runtime","__scopeTabs","useId","Primitive","orientation","forwardedRef","TAB_LIST_NAME","TabsList","listProps","rovingFocusGroupScope","RovingFocusGroup.Root","TRIGGER_NAME","TabsTrigger","triggerProps","triggerId","makeTriggerId","contentId","makeContentId","isSelected","RovingFocusGroup.Item","disabled","composeEventHandlers","event","isAutomaticActivation","CONTENT_NAME","TabsContent","contentProps","isMountAnimationPreventedRef","rAF","Presence","forceMount","present","children","baseId","Root2","List","Trigger","Content","NAME","Toggle","__name$1","pressedProp","buttonProps","pressed","setPressed","onPressedChange","defaultPressed","TOGGLE_GROUP_NAME","createToggleGroupContext","createToggleGroupScope","ToggleGroup","toggleGroupProps","type","ToggleGroupImplSingle","singleProps","ToggleGroupImplMultiple","multipleProps","ToggleGroupValueProvider","useToggleGroupValueContext","toggleGroupSingleProps","ToggleGroupImpl","toggleGroupMultipleProps","handleButtonActivate","prevValue","itemValue","handleButtonDeactivate","value2","ToggleGroupContext","useToggleGroupContext","__scopeToggleGroup","commonProps","rovingFocus","ITEM_NAME","ToggleGroupItem","valueContext","ref","ToggleGroupItemImpl","itemProps","typeProps","TabsPrimitive.Root","cn","className","TabsPrimitive.List","variant","TabsPrimitive.Trigger","TabsPrimitive.Content","EntrySiblings","useFieldsEnvironment","values","useEntryForm","state","siblings","useMemo","model","SiblingValuesContext","FieldsProvider","FieldsEnvironmentContext","environment","EntryFormStoreContext","store","useTopLevelValue","field","useCallback","EditorErrorBoundary","Component","logError","error","info","FieldEditor","useTranslation","control","BuiltInComponent","builtIn","_Fragment","resolved","builtInProps","contractProps","Suspense","Skeleton","FieldMessages","message","PATTERNS","SLUG_PATTERN","UID_PATTERN","DATE_PATTERN","DATETIME_PATTERN","TIME_PATTERN","DECIMAL_PATTERN","BIGINTEGER_PATTERN","issue","code","checkLength","settings","checkRange","checkCount","count","parsesAsJson","checkCode","checkText","pattern","option","clientIssuesOf","isEmptyValue","toList","fieldDomId","prefix","path","toEditorField","toEditorModel","definition","interpolate","name","match","translateKey","i18next","toEditorContext","fallback","pointerOf","segment","issuesByPath","map","issues","countIssuesUnder","list","FORMAT_KEYS","hasFormatKey","setting","describeIssue","t","withCount","settingKey","choicesOf","stringOption","fromChoice","choice","toChoice","isMultiple","CheckboxGroup","selected","choices","horizontal","labelId","describedBy","validation","Checkbox","inputId","readOnly","item","checked","onChange","Label","CheckboxInput","inputAria","HEX_COLOUR","EMPTY_PICKER_VALUE","presetsOf","presets","preset","swatchStyle","colour","ColorInput","textValue","Input","AddItemButton","Button","Plus","label","CHIP_CLASSES","ScopeBadge","localized","Languages","Popover","PopoverTrigger","Globe","PopoverContent","ScopeIcon","Icon","Tooltip","TooltipTrigger","TooltipContent","FieldControl","memo","useFieldControl","LabelElement","inline","layout","topLevel","WIDTH_GRID_CLASSES","WIDTH_CLASSES","widthClassOf","width","fieldGridModeOf","entryLayoutOf","COMPACT_TYPES","isCompact","FieldGrid","mode","fields","renderField","isAssetView","mediaIdOf","collect","liveFields","componentOfItem","components","id","component","COMPONENT_KEY","fromApiValue","convert","withClientKey","toFormValues","data","defaultFormValues","newComponentItem","zoned","toInputValue","stripClientKeys","dirtyKeysOf","isSameContent","baseline","buildPatch","buildCreateData","mergeSaved","current","saved","sent","ComponentItemFields","wrapped","renderFieldFooter","onItemChange","MAX_SUMMARY","truncate","summarizeValue","richTextPlainText","valueLabel","TEXTUAL_TYPES","summarizeItem","titleField","candidates","summary","useCollapsedItems","collapsed","setCollapsed","useState","startCollapsed","initialKeys","useFocusNewItem","previous","useRef","added","domId","DRAG_TYPE","useItemDrag","from","setFrom","over","setOver","reset","index","move","useItemIssueCount","ItemCard","bodyId","onKeyDown","onMove","canvas","appearance","actionClasses","drag","issueCount","editable","title","GripVertical","onToggle","ChevronRight","StatusChip","ArrowUp","ArrowDown","onDuplicate","Copy","onRemove","Trash2","ItemInserter","menu","useDeferredMenuAction","DropdownMenu","DropdownMenuTrigger","DropdownMenuContent","DropdownMenuGroup","DropdownMenuLabel","InsertMenuItem","Boxes","onInsert","Block","itemPath","\"__component\"","itemKey","to","CanvasItemList","Fragment","insertable","newItem","componentOf","toggle","hasRoomFor","max","emptyListMinimum","min","EmptyListRow","minimum","EmptyState","useListEditor","items","commit","clientKeyOf","at","moveItem","copy","RepeatableItem","CanvasRepeatable","room","add","empty","Repeatable","Single","ComponentField","ClearButton","onClear","X","DateInput","pad","length","toDateTimeInput","iso","date","year","month","day","hours","minutes","seconds","utc","fromDateTimeInput","withSeconds","localTimeZone","DateTimeInput","hintId","allowedComponentsOf","useAllowedComponents","AddSectionMenu","allowed","DropdownMenuItem","onAdd","ZoneItem","candidate","CanvasZone","DynamicZoneField","FormZone","allCollapsed","setAll","ChevronsUpDown","ParseError","DEFAULT_ROWS","INDENT","format","parse","JsonEditor","setText","problem","setProblem","seen","setSeen","parsed","isDeepEqual","errorId","Textarea","numberOption","Braces","GalleryTile","asset","useMediaAsset","assetId","Thumbnail","ImageOff","ArrowRight","Gallery","dropping","setDropping","uploading","setUploading","acceptsFiles","canAdd","uploadMedia","onDrop","files","file","toast","ids","onPick","ImagePlus","MediaField","useMediaPermissions","multiple","onBlur","pick","picked","chosen","reportError","AssetTile","canWrite","INTEGER","NUMBER","trimmed","number","NumberInput","invalid","setInvalid","parseErrorId","integer","RadioInput","RadioGroup","RadioGroupItem","MAX_LOOKUP","useEntryLabels","titleFieldOf","lookup","query","locale","useEntryList","TopLevelField","EntryFields","withoutIssuesUnder","apiKey","createEntryFormStore","createStore","initial","local","selectDirtyKeys","contentIssuesOf","ShapioApiError","referrersOf","referrers","isEditConflict","InlineCreateSheet","outer","dirty","useStore","create","useCreateEntry","useDiscardGuard","open","onClose","submit","onCreated","Sheet","requestOpenChange","SheetContent","SheetHeader","SheetTitle","SheetBody","FormError","SheetFooter","SubmitButton","discardPrompt","MD_QUERY","subscribe","getSnapshot","useIsMdUp","useSyncExternalStore","useActiveOption","rememberedId","setActiveId","activeId","delta","PAGE_SIZE","SEARCH_DEBOUNCE_MS","Results","listboxId","q","useDebouncedValue","searchable","isSearchable","exclude","active","optionId","activeDescendant","choose","onUnpick","full","Search","listClassName","Check","labelOf","LoadingState","ErrorState","RelationPicker","isMdUp","titleId","triggerRef","creatingRef","onOpenChange","startCreate","onCloseAutoFocus","creating","trigger","onFocusFallback","onCreate","results","actions","canCreate","SheetTrigger","RelationField","searching","setSearching","setCreating","listRef","labels","canAddMore","labelFor","entryTitle","shortId","IconTile","Layers","toggleVariants","cva","ToggleGroupPrimitive.Root","size","ToggleGroupPrimitive.Item","Segmented","MultiSelect","ChevronDown","DropdownMenuCheckboxItem","SelectInput","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Counter","counter","SOFT_MAX_BY_FIELD_ID","SEO_FIELD_IDS","seoCounterOf","fieldId","BUILT_IN_TYPES","seoComponentDefinition","seoKeysOf","localeChainOf","fallbackLocale","locales","start","chain","entry","seoPreviewOf","localeDefaults","seoDefaultsForLocale","defaults","localeChain","fallbackTitle","useSeoPreview","useSiteSeoDefaults","useLocales","siteName","useMe","titleKey","effectiveTitleField","slugKey","slug","preview","host","urlLine","Preview","headingId","noindex","renderCounter","SeoGroup","noindexKey","SeoField","isSeoField","slugify","useSourceText","useSiblingValues","sourceId","source","SlugInput","sourceText","following","setFollowing","lastSource","Link2","Link2Off","maxLength","countId","TextareaControl","INPUT_TYPES","TextInput","SECONDS_PER_MINUTE","TimeInput","Switch","RichTextField","lazy","module","CodeEditor","BUILT_IN_EDITORS","SEO_EDITOR_ID","builtInEditorFor","compatible","EDITOR_CATALOGUE","DEFAULT_EDITORS","resolveEditor","isCustomEditorId","custom","runtimeEditors","NESTING_TYPES","useFieldMessages","serverIssues","revealed","nesting","server","client","known","touch","messages","descriptionId","errorsId","editorField","editorModel","owner","_definition","_path","_appearance","useEditorManifest","useQuery","queryKeys","adminApi","NO_RUNTIME_EDITORS","editorModuleUrl","apiBaseUrl","importModule","__vitePreload","url","loadRuntimeEditors","editors","problems","manifest","load","definitions","isEditorDefinition","useRuntimeEditors","modules","restEndpoints","isModelDefinition","delivery","routeKeyOf","admin","collection","RICH_TEXT_SAMPLE","MEDIA_SAMPLE","MAX_SAMPLE_DEPTH","sampleValue","many","sampleObject","depth","SYSTEM_SAMPLE","restResponseSample","meta","body","listOf","graphqlFieldType","nameOf","toTypeName","READ_ARGS","graphqlSdl","system","line","queries","collectionQueryName","mutations","MUTATION_PREFIXES"],"ignoreList":[1,2,3,4,5,6],"sources":["../../../../packages/schema/src/seo/resolve.ts","../../../../node_modules/.pnpm/lucide-react@1.49.0_@types+react@19.3.0_react@19.3.0/node_modules/lucide-react/dist/esm/icons/arrow-left.mjs","../../../../node_modules/.pnpm/lucide-react@1.49.0_@types+react@19.3.0_react@19.3.0/node_modules/lucide-react/dist/esm/icons/chevrons-down-up.mjs","../../../../node_modules/.pnpm/lucide-react@1.49.0_@types+react@19.3.0_react@19.3.0/node_modules/lucide-react/dist/esm/icons/rotate-ccw-clock.mjs","../../../../node_modules/.pnpm/@radix-ui+react-tabs@1.1.21_@types+react-dom@19.3.0_@types+react@19.3.0__@types+react@1_c98ff049ac6c06001c8e28faf2978e1a/node_modules/@radix-ui/react-tabs/dist/index.mjs","../../../../node_modules/.pnpm/@radix-ui+react-toggle@1.1.18_@types+react-dom@19.3.0_@types+react@19.3.0__@types+react_3e4dd2eba2183dd95abdddf4ecd4003f/node_modules/@radix-ui/react-toggle/dist/index.mjs","../../../../node_modules/.pnpm/@radix-ui+react-toggle-group@1.1.19_@types+react-dom@19.3.0_@types+react@19.3.0__@types_2e29e58635a712cf598e39122b42ab8c/node_modules/@radix-ui/react-toggle-group/dist/index.mjs","../../src/components/ui/tabs.tsx","../../src/fields/form/EntrySiblings/index.tsx","../../src/fields/form/FieldsProvider/index.tsx","../../src/fields/hooks/useTopLevelValue.ts","../../src/fields/runtime/EditorErrorBoundary/index.tsx","../../src/fields/FieldEditor/index.tsx","../../src/fields/FieldMessages/index.tsx","../../src/fields/helpers/clientValidation.ts","../../src/fields/helpers/domIds.ts","../../src/fields/helpers/editorContext.ts","../../src/fields/helpers/issues.ts","../../src/fields/helpers/choices.ts","../../src/fields/CheckboxGroup/index.tsx","../../src/fields/CheckboxInput/index.tsx","../../src/fields/ColorInput/index.tsx","../../src/fields/AddItemButton/index.tsx","../../src/fields/ScopeBadge/index.tsx","../../src/fields/ScopeIcon/index.tsx","../../src/fields/FieldControl/index.tsx","../../src/fields/helpers/widthClasses.ts","../../src/fields/FieldGrid/index.tsx","../../src/fields/helpers/formValues.ts","../../src/fields/ComponentItemFields/index.tsx","../../src/fields/helpers/summary.ts","../../src/fields/hooks/useCollapsedItems.ts","../../src/fields/hooks/useFocusNewItem.ts","../../src/fields/hooks/useItemDrag.ts","../../src/fields/hooks/useItemIssueCount.ts","../../src/fields/ItemCard/index.tsx","../../src/fields/ItemInserter/index.tsx","../../src/fields/CanvasItemList/index.tsx","../../src/fields/helpers/listLimits.ts","../../src/fields/EmptyListRow/index.tsx","../../src/fields/hooks/useListEditor.ts","../../src/fields/ComponentField/index.tsx","../../src/fields/ClearButton/index.tsx","../../src/fields/DateInput/index.tsx","../../src/fields/helpers/dates.ts","../../src/fields/DateTimeInput/index.tsx","../../src/fields/hooks/useAllowedComponents.ts","../../src/fields/DynamicZoneField/AddSectionMenu/index.tsx","../../src/fields/DynamicZoneField/index.tsx","../../src/fields/ParseError/index.tsx","../../src/fields/JsonEditor/index.tsx","../../src/fields/MediaField/GalleryTile/index.tsx","../../src/fields/MediaField/Gallery/index.tsx","../../src/fields/MediaField/index.tsx","../../src/fields/NumberInput/index.tsx","../../src/fields/RadioInput/index.tsx","../../src/fields/hooks/useEntryLabels.ts","../../src/fields/form/TopLevelField/index.tsx","../../src/fields/form/EntryFields/index.tsx","../../src/fields/form/store.ts","../../src/fields/helpers/apiErrors.ts","../../src/fields/RelationField/InlineCreateSheet/index.tsx","../../src/fields/hooks/useIsMdUp.ts","../../src/fields/RelationField/RelationPicker/hooks/useActiveOption.ts","../../src/fields/RelationField/RelationPicker/Results/index.tsx","../../src/fields/RelationField/RelationPicker/index.tsx","../../src/fields/RelationField/index.tsx","../../src/components/ui/toggle.tsx","../../src/components/ui/toggle-group.tsx","../../src/fields/Segmented/index.tsx","../../src/fields/SelectInput/index.tsx","../../src/fields/SeoField/Counter/index.tsx","../../src/fields/SeoField/helpers.ts","../../src/fields/SeoField/hooks/useSeoPreview.ts","../../src/fields/SeoField/Preview/index.tsx","../../src/fields/SeoField/index.tsx","../../src/fields/helpers/slugify.ts","../../src/fields/SlugInput/index.tsx","../../src/fields/Textarea/index.tsx","../../src/fields/TextInput/index.tsx","../../src/fields/TimeInput/index.tsx","../../src/fields/Toggle/index.tsx","../../src/fields/registry.ts","../../src/fields/hooks/useFieldControl.ts","../../src/api/editors.ts","../../src/fields/runtime/loader.ts","../../src/fields/runtime/useRuntimeEditors.ts","../../src/features/Develop/Schema/helpers/shapes.ts"],"sourcesContent":["import type { SeoLocaleDefaults } from './defaults.js';\nimport type { SeoFieldKey } from './ids.js';\nimport { applyTitleTemplate } from './locale.js';\n\n/** The API IDs under which a delivered SEO value carries each built-in field (absent: removed or retyped). */\nexport type SeoKeys = Partial<Record<SeoFieldKey, string>>;\n\n/** The API IDs the built-in component is created with. */\nexport const DEFAULT_SEO_KEYS: Required<SeoKeys> = {\n title: 'title',\n description: 'description',\n image: 'image',\n canonical: 'canonical',\n noindex: 'noindex',\n};\n\nexport type ResolveSeoContext = {\n /** The site's default texts for the entry's locale (`seoDefaultsForLocale`). */\n defaults: SeoLocaleDefaults;\n /** The default social image in the delivered asset shape, or null. */\n image: unknown;\n /** The entry's own title (its title field) when the SEO title is empty; null when none is readable. */\n fallbackTitle: string | null;\n /** Where each field sits in `raw`; defaults to the built-in API IDs. */\n keys?: SeoKeys;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst text = (value: unknown): string | null =>\n typeof value === 'string' && value.trim() !== '' ? value : null;\n\n/**\n * The effective SEO values of one delivered entry, in the same shape as the raw value (plan seo-fields): the\n * title is the entry's SEO title, else its own title, through the site's template (the bare site name when\n * neither exists, never templated); description and image fall back to the site's defaults; canonical stays\n * the entry's value or null; noindex is a boolean. Other keys (fields a user added) pass through. Pure.\n */\nexport const resolveSeo = (raw: unknown, context: ResolveSeoContext): Record<string, unknown> => {\n const keys = context.keys ?? DEFAULT_SEO_KEYS;\n const output: Record<string, unknown> = isRecord(raw) ? { ...raw } : {};\n const value = (key: SeoFieldKey) => (keys[key] === undefined ? undefined : output[keys[key]]);\n const set = (key: SeoFieldKey, next: unknown) => {\n if (keys[key] !== undefined) {\n output[keys[key]] = next;\n }\n };\n const base = text(value('title')) ?? text(context.fallbackTitle);\n set(\n 'title',\n base !== null\n ? applyTitleTemplate(base, context.defaults.titleTemplate)\n : (context.defaults.siteName ?? null),\n );\n set('description', text(value('description')) ?? context.defaults.description ?? null);\n set('image', value('image') ?? context.image ?? null);\n set('canonical', text(value('canonical')));\n set('noindex', value('noindex') === true);\n return output;\n};\n","/**\n * @license lucide-react v1.49.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"arrow-left\",\n size: 24,\n node: [\n [\"path\", { d: \"m12 19-7-7 7-7\", key: \"1l729n\" }],\n [\"path\", { d: \"M19 12H5\", key: \"x3x0zl\" }]\n ]\n};\n__iconData.node;\nconst ArrowLeft = createLucideIcon(__iconData);\n\nexport { __iconData, ArrowLeft as default };\n//# sourceMappingURL=arrow-left.mjs.map\n","/**\n * @license lucide-react v1.49.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"chevrons-down-up\",\n size: 24,\n node: [\n [\"path\", { d: \"m7 20 5-5 5 5\", key: \"13a0gw\" }],\n [\"path\", { d: \"m7 4 5 5 5-5\", key: \"1kwcof\" }]\n ]\n};\n__iconData.node;\nconst ChevronsDownUp = createLucideIcon(__iconData);\n\nexport { __iconData, ChevronsDownUp as default };\n//# sourceMappingURL=chevrons-down-up.mjs.map\n","/**\n * @license lucide-react v1.49.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"rotate-ccw-clock\",\n size: 24,\n node: [\n [\"path\", { d: \"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"1357e3\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }],\n [\"path\", { d: \"M12 7v5l4 2\", key: \"1fdv2h\" }]\n ],\n aliases: [\"history\"]\n};\n__iconData.node;\nconst RotateCcwClock = createLucideIcon(__iconData);\n\nexport { __iconData, RotateCcwClock as default };\n//# sourceMappingURL=rotate-ccw-clock.mjs.map\n","\"use client\";\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\n// src/tabs.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { createRovingFocusGroupScope } from \"@radix-ui/react-roving-focus\";\nimport { Presence } from \"@radix-ui/react-presence\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as RovingFocusGroup from \"@radix-ui/react-roving-focus\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { jsx } from \"react/jsx-runtime\";\nvar TABS_NAME = \"Tabs\";\nvar [createTabsContext, createTabsScope] = createContextScope(TABS_NAME, [\n createRovingFocusGroupScope\n]);\nvar useRovingFocusGroupScope = createRovingFocusGroupScope();\nvar [TabsProvider, useTabsContext] = createTabsContext(TABS_NAME);\nvar Tabs = /* @__PURE__ */ React.forwardRef(\n // blank line to reduce diff noise\n /* @__PURE__ */ __name(function Tabs2(props, forwardedRef) {\n const {\n __scopeTabs,\n value: valueProp,\n onValueChange,\n defaultValue,\n orientation = \"horizontal\",\n dir,\n activationMode = \"automatic\",\n ...tabsProps\n } = props;\n const direction = useDirection(dir);\n const [value, setValue] = useControllableState({\n prop: valueProp,\n onChange: onValueChange,\n defaultProp: defaultValue ?? \"\",\n caller: TABS_NAME\n });\n return /* @__PURE__ */ jsx(\n TabsProvider,\n {\n scope: __scopeTabs,\n baseId: useId(),\n value,\n onValueChange: setValue,\n orientation,\n dir: direction,\n activationMode,\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n dir: direction,\n \"data-orientation\": orientation,\n ...tabsProps,\n ref: forwardedRef\n }\n )\n }\n );\n }, \"Tabs\")\n);\nvar TAB_LIST_NAME = \"TabsList\";\nvar TabsList = /* @__PURE__ */ React.forwardRef(\n // blank line to reduce diff noise\n /* @__PURE__ */ __name(function TabsList2(props, forwardedRef) {\n const { __scopeTabs, loop = true, ...listProps } = props;\n const context = useTabsContext(TAB_LIST_NAME, __scopeTabs);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);\n return /* @__PURE__ */ jsx(\n RovingFocusGroup.Root,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n orientation: context.orientation,\n dir: context.dir,\n loop,\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n role: \"tablist\",\n \"aria-orientation\": context.orientation,\n ...listProps,\n ref: forwardedRef\n }\n )\n }\n );\n }, \"TabsList\")\n);\nvar TRIGGER_NAME = \"TabsTrigger\";\nvar TabsTrigger = /* @__PURE__ */ React.forwardRef(\n /* @__PURE__ */ __name(function TabsTrigger2(props, forwardedRef) {\n const { __scopeTabs, value, disabled = false, ...triggerProps } = props;\n const context = useTabsContext(TRIGGER_NAME, __scopeTabs);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);\n const triggerId = makeTriggerId(context.baseId, value);\n const contentId = makeContentId(context.baseId, value);\n const isSelected = value === context.value;\n return /* @__PURE__ */ jsx(\n RovingFocusGroup.Item,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n focusable: !disabled,\n active: isSelected,\n children: /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n role: \"tab\",\n \"aria-selected\": isSelected,\n \"aria-controls\": contentId,\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n \"data-disabled\": disabled ? \"\" : void 0,\n disabled,\n id: triggerId,\n ...triggerProps,\n ref: forwardedRef,\n onMouseDown: composeEventHandlers(props.onMouseDown, (event) => {\n if (!disabled && event.button === 0 && event.ctrlKey === false) {\n context.onValueChange(value);\n } else {\n event.preventDefault();\n }\n }),\n onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {\n if (disabled || event.target !== event.currentTarget) {\n return;\n }\n if ([\" \", \"Enter\"].includes(event.key)) {\n context.onValueChange(value);\n }\n }),\n onFocus: composeEventHandlers(props.onFocus, () => {\n const isAutomaticActivation = context.activationMode !== \"manual\";\n if (!isSelected && !disabled && isAutomaticActivation) {\n context.onValueChange(value);\n }\n })\n }\n )\n }\n );\n }, \"TabsTrigger\")\n);\nvar CONTENT_NAME = \"TabsContent\";\nvar TabsContent = /* @__PURE__ */ React.forwardRef(\n /* @__PURE__ */ __name(function TabsContent2(props, forwardedRef) {\n const { __scopeTabs, value, forceMount, children, ...contentProps } = props;\n const context = useTabsContext(CONTENT_NAME, __scopeTabs);\n const triggerId = makeTriggerId(context.baseId, value);\n const contentId = makeContentId(context.baseId, value);\n const isSelected = value === context.value;\n const isMountAnimationPreventedRef = React.useRef(isSelected);\n React.useEffect(() => {\n const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);\n return () => cancelAnimationFrame(rAF);\n }, []);\n return /* @__PURE__ */ jsx(Presence, { present: forceMount || isSelected, children: ({ present }) => /* @__PURE__ */ jsx(\n Primitive.div,\n {\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n \"data-orientation\": context.orientation,\n role: \"tabpanel\",\n \"aria-labelledby\": triggerId,\n hidden: !present,\n id: contentId,\n tabIndex: 0,\n ...contentProps,\n ref: forwardedRef,\n style: {\n ...props.style,\n animationDuration: isMountAnimationPreventedRef.current ? \"0s\" : void 0\n },\n children: present && children\n }\n ) });\n }, \"TabsContent\")\n);\nfunction makeTriggerId(baseId, value) {\n return `${baseId}-trigger-${value}`;\n}\n__name(makeTriggerId, \"makeTriggerId\");\nfunction makeContentId(baseId, value) {\n return `${baseId}-content-${value}`;\n}\n__name(makeContentId, \"makeContentId\");\nvar Root2 = Tabs;\nvar List = TabsList;\nvar Trigger = TabsTrigger;\nvar Content = TabsContent;\nexport {\n Content,\n List,\n Root2 as Root,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Trigger,\n createTabsScope\n};\n//# sourceMappingURL=index.mjs.map\n","\"use client\";\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\n// src/toggle.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { jsx } from \"react/jsx-runtime\";\nvar NAME = \"Toggle\";\nvar Toggle = /* @__PURE__ */ React.forwardRef(\n /* @__PURE__ */ __name(function Toggle2(props, forwardedRef) {\n const { pressed: pressedProp, defaultPressed, onPressedChange, ...buttonProps } = props;\n const [pressed, setPressed] = useControllableState({\n prop: pressedProp,\n onChange: onPressedChange,\n defaultProp: defaultPressed ?? false,\n caller: NAME\n });\n return /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n \"aria-pressed\": pressed,\n \"data-state\": pressed ? \"on\" : \"off\",\n \"data-disabled\": props.disabled ? \"\" : void 0,\n ...buttonProps,\n ref: forwardedRef,\n onClick: composeEventHandlers(props.onClick, () => {\n if (!props.disabled) {\n setPressed(!pressed);\n }\n })\n }\n );\n }, \"Toggle\")\n);\nvar Root = Toggle;\nexport {\n Root,\n Toggle\n};\n//# sourceMappingURL=index.mjs.map\n","\"use client\";\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\n// src/toggle-group.tsx\nimport * as React from \"react\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as RovingFocusGroup from \"@radix-ui/react-roving-focus\";\nimport { createRovingFocusGroupScope } from \"@radix-ui/react-roving-focus\";\nimport { Toggle } from \"@radix-ui/react-toggle\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { jsx } from \"react/jsx-runtime\";\nvar TOGGLE_GROUP_NAME = \"ToggleGroup\";\nvar [createToggleGroupContext, createToggleGroupScope] = createContextScope(TOGGLE_GROUP_NAME, [\n createRovingFocusGroupScope\n]);\nvar useRovingFocusGroupScope = createRovingFocusGroupScope();\nvar ToggleGroup = /* @__PURE__ */ React.forwardRef(/* @__PURE__ */ __name(function ToggleGroup2(props, forwardedRef) {\n const { type, ...toggleGroupProps } = props;\n if (type === \"single\") {\n const singleProps = toggleGroupProps;\n return /* @__PURE__ */ jsx(ToggleGroupImplSingle, { role: \"radiogroup\", ...singleProps, ref: forwardedRef });\n }\n if (type === \"multiple\") {\n const multipleProps = toggleGroupProps;\n return /* @__PURE__ */ jsx(ToggleGroupImplMultiple, { role: \"toolbar\", ...multipleProps, ref: forwardedRef });\n }\n throw new Error(`Missing prop \\`type\\` expected on \\`${TOGGLE_GROUP_NAME}\\``);\n}, \"ToggleGroup\"));\nvar [ToggleGroupValueProvider, useToggleGroupValueContext] = createToggleGroupContext(TOGGLE_GROUP_NAME);\nvar ToggleGroupImplSingle = /* @__PURE__ */ React.forwardRef(/* @__PURE__ */ __name(function ToggleGroupImplSingle2(props, forwardedRef) {\n const {\n value: valueProp,\n defaultValue,\n onValueChange = /* @__PURE__ */ __name(() => {\n }, \"onValueChange\"),\n ...toggleGroupSingleProps\n } = props;\n const [value, setValue] = useControllableState({\n prop: valueProp,\n defaultProp: defaultValue ?? \"\",\n onChange: onValueChange,\n caller: TOGGLE_GROUP_NAME\n });\n return /* @__PURE__ */ jsx(\n ToggleGroupValueProvider,\n {\n scope: props.__scopeToggleGroup,\n type: \"single\",\n value: React.useMemo(() => value ? [value] : [], [value]),\n onItemActivate: setValue,\n onItemDeactivate: React.useCallback(() => setValue(\"\"), [setValue]),\n children: /* @__PURE__ */ jsx(ToggleGroupImpl, { ...toggleGroupSingleProps, ref: forwardedRef })\n }\n );\n}, \"ToggleGroupImplSingle\"));\nvar ToggleGroupImplMultiple = /* @__PURE__ */ React.forwardRef(/* @__PURE__ */ __name(function ToggleGroupImplMultiple2(props, forwardedRef) {\n const {\n value: valueProp,\n defaultValue,\n onValueChange = /* @__PURE__ */ __name(() => {\n }, \"onValueChange\"),\n ...toggleGroupMultipleProps\n } = props;\n const [value, setValue] = useControllableState({\n prop: valueProp,\n defaultProp: defaultValue ?? [],\n onChange: onValueChange,\n caller: TOGGLE_GROUP_NAME\n });\n const handleButtonActivate = React.useCallback(\n (itemValue) => setValue((prevValue = []) => [...prevValue, itemValue]),\n [setValue]\n );\n const handleButtonDeactivate = React.useCallback(\n (itemValue) => setValue((prevValue = []) => prevValue.filter((value2) => value2 !== itemValue)),\n [setValue]\n );\n return /* @__PURE__ */ jsx(\n ToggleGroupValueProvider,\n {\n scope: props.__scopeToggleGroup,\n type: \"multiple\",\n value,\n onItemActivate: handleButtonActivate,\n onItemDeactivate: handleButtonDeactivate,\n children: /* @__PURE__ */ jsx(ToggleGroupImpl, { ...toggleGroupMultipleProps, ref: forwardedRef })\n }\n );\n}, \"ToggleGroupImplMultiple\"));\nvar [ToggleGroupContext, useToggleGroupContext] = createToggleGroupContext(TOGGLE_GROUP_NAME);\nvar ToggleGroupImpl = /* @__PURE__ */ React.forwardRef(\n // blank line to reduce diff noise\n /* @__PURE__ */ __name(function ToggleGroupImpl2(props, forwardedRef) {\n const {\n __scopeToggleGroup,\n disabled = false,\n rovingFocus = true,\n orientation,\n dir,\n loop = true,\n ...toggleGroupProps\n } = props;\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeToggleGroup);\n const direction = useDirection(dir);\n const commonProps = { dir: direction, ...toggleGroupProps };\n return /* @__PURE__ */ jsx(ToggleGroupContext, { scope: __scopeToggleGroup, rovingFocus, disabled, children: rovingFocus ? /* @__PURE__ */ jsx(\n RovingFocusGroup.Root,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n orientation,\n dir: direction,\n loop,\n children: /* @__PURE__ */ jsx(Primitive.div, { ...commonProps, ref: forwardedRef })\n }\n ) : /* @__PURE__ */ jsx(Primitive.div, { ...commonProps, ref: forwardedRef }) });\n }, \"ToggleGroupImpl\")\n);\nvar ITEM_NAME = \"ToggleGroupItem\";\nvar ToggleGroupItem = /* @__PURE__ */ React.forwardRef(\n // blank line to reduce diff noise\n /* @__PURE__ */ __name(function ToggleGroupItem2(props, forwardedRef) {\n const valueContext = useToggleGroupValueContext(ITEM_NAME, props.__scopeToggleGroup);\n const context = useToggleGroupContext(ITEM_NAME, props.__scopeToggleGroup);\n const rovingFocusGroupScope = useRovingFocusGroupScope(props.__scopeToggleGroup);\n const pressed = valueContext.value.includes(props.value);\n const disabled = context.disabled || props.disabled;\n const commonProps = { ...props, pressed, disabled };\n const ref = React.useRef(null);\n return context.rovingFocus ? /* @__PURE__ */ jsx(\n RovingFocusGroup.Item,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n focusable: !disabled,\n active: pressed,\n ref,\n children: /* @__PURE__ */ jsx(ToggleGroupItemImpl, { ...commonProps, ref: forwardedRef })\n }\n ) : /* @__PURE__ */ jsx(ToggleGroupItemImpl, { ...commonProps, ref: forwardedRef });\n }, \"ToggleGroupItem\")\n);\nvar ToggleGroupItemImpl = /* @__PURE__ */ React.forwardRef(\n // blank line to reduce diff noise\n /* @__PURE__ */ __name(function ToggleGroupItemImpl2(props, forwardedRef) {\n const { __scopeToggleGroup, value, ...itemProps } = props;\n const valueContext = useToggleGroupValueContext(ITEM_NAME, __scopeToggleGroup);\n const singleProps = { role: \"radio\", \"aria-checked\": props.pressed, \"aria-pressed\": void 0 };\n const typeProps = valueContext.type === \"single\" ? singleProps : void 0;\n return /* @__PURE__ */ jsx(\n Toggle,\n {\n ...typeProps,\n ...itemProps,\n ref: forwardedRef,\n onPressedChange: (pressed) => {\n if (pressed) {\n valueContext.onItemActivate(value);\n } else {\n valueContext.onItemDeactivate(value);\n }\n }\n }\n );\n }, \"ToggleGroupItemImpl\")\n);\nexport {\n ToggleGroupItem as Item,\n ToggleGroup as Root,\n ToggleGroup,\n ToggleGroupItem,\n createToggleGroupScope\n};\n//# sourceMappingURL=index.mjs.map\n","import { Tabs as TabsPrimitive } from 'radix-ui';\nimport * as React from 'react';\nimport { cn } from '@/helpers/cn';\n\nfunction Tabs({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {\n return <TabsPrimitive.Root data-slot=\"tabs\" className={cn('flex flex-col gap-2', className)} {...props} />;\n}\n\n// Shapio: `underline` is the page-level style (2px primary bar under the active tab, DESIGN.md); `default`\n// is the segmented control for small in-panel switches.\nfunction TabsList({\n className,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.List> & { variant?: 'default' | 'underline' }) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n data-variant={variant}\n className={cn(\n 'group/tabs-list inline-flex w-fit items-center text-muted-foreground',\n variant === 'default' && 'h-9 justify-center rounded-lg bg-muted p-[3px]',\n variant === 'underline' && 'h-10 w-full justify-start gap-5 border-b',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"inline-flex items-center justify-center gap-1.5 text-sm whitespace-nowrap transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n // Segmented\n 'group-data-[variant=default]/tabs-list:h-[calc(100%-1px)] group-data-[variant=default]/tabs-list:flex-1 group-data-[variant=default]/tabs-list:rounded-md group-data-[variant=default]/tabs-list:border group-data-[variant=default]/tabs-list:border-transparent group-data-[variant=default]/tabs-list:px-2 group-data-[variant=default]/tabs-list:py-1 group-data-[variant=default]/tabs-list:font-medium group-data-[variant=default]/tabs-list:text-foreground group-data-[variant=default]/tabs-list:data-[state=active]:bg-background group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm dark:group-data-[variant=default]/tabs-list:text-muted-foreground dark:group-data-[variant=default]/tabs-list:data-[state=active]:border-input dark:group-data-[variant=default]/tabs-list:data-[state=active]:bg-input/30 dark:group-data-[variant=default]/tabs-list:data-[state=active]:text-foreground',\n // Underline\n 'group-data-[variant=underline]/tabs-list:relative group-data-[variant=underline]/tabs-list:h-full group-data-[variant=underline]/tabs-list:rounded-sm group-data-[variant=underline]/tabs-list:px-0.5 group-data-[variant=underline]/tabs-list:font-semibold group-data-[variant=underline]/tabs-list:after:absolute group-data-[variant=underline]/tabs-list:after:inset-x-0 group-data-[variant=underline]/tabs-list:after:-bottom-px group-data-[variant=underline]/tabs-list:after:h-0.5 group-data-[variant=underline]/tabs-list:after:rounded-full group-data-[variant=underline]/tabs-list:hover:text-foreground group-data-[variant=underline]/tabs-list:data-[state=active]:text-foreground group-data-[variant=underline]/tabs-list:data-[state=active]:after:bg-primary',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return (\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n // Shapio: the panel is a Tab stop (Radix), so it shows the same focus ring as every other control.\n className={cn(\n 'flex-1 rounded-md outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent };\n","import type { ReactNode } from 'react';\nimport { useMemo } from 'react';\nimport { SiblingValuesContext, useEntryForm, useFieldsEnvironment } from '../context';\n\ntype EntrySiblingsProps = { children: ReactNode };\n\n/** Gives slug fields their source field's value; only its consumers re-render as values change. */\nexport const EntrySiblings = ({ children }: EntrySiblingsProps) => {\n const { model } = useFieldsEnvironment();\n const values = useEntryForm((state) => state.values);\n const siblings = useMemo(() => ({ definition: model, values }), [model, values]);\n return <SiblingValuesContext.Provider value={siblings}>{children}</SiblingValuesContext.Provider>;\n};\n","import type { ReactNode } from 'react';\nimport { EntryFormStoreContext, FieldsEnvironmentContext, type FieldsEnvironment } from '../context';\nimport type { EntryFormStore } from '../store';\n\ntype FieldsProviderProps = { environment: FieldsEnvironment; store: EntryFormStore; children: ReactNode };\n\nexport const FieldsProvider = ({ environment, store, children }: FieldsProviderProps) => (\n <FieldsEnvironmentContext.Provider value={environment}>\n <EntryFormStoreContext.Provider value={store}>{children}</EntryFormStoreContext.Provider>\n </FieldsEnvironmentContext.Provider>\n);\n","import type { FieldDefinition } from '@shapio/schema';\nimport { useCallback } from 'react';\nimport { useEntryForm } from '../form/context';\n\n/** One top-level field's value and setter: subscribes to that value only, so typing re-renders one field. */\nexport const useTopLevelValue = (field: FieldDefinition) => {\n const value = useEntryForm((state) => state.values[field.apiKey]);\n const setValue = useEntryForm((state) => state.setValue);\n const onChange = useCallback((next: unknown) => setValue(field.apiKey, next), [setValue, field.apiKey]);\n return { value, onChange };\n};\n","import { Component, type ErrorInfo, type ReactNode } from 'react';\nimport { logError } from '@/helpers/reportError';\n\ntype EditorErrorBoundaryProps = {\n editorId: string;\n /** Rendered instead of the editor once it has thrown. */\n fallback: ReactNode;\n children: ReactNode;\n};\n\ntype EditorErrorBoundaryState = { failed: boolean };\n\n/**\n * Keeps a crashing custom editor from taking the whole form down: the field falls back to its built-in\n * editor. React only offers error boundaries as class components, so this is the one class in the admin.\n */\nexport class EditorErrorBoundary extends Component<EditorErrorBoundaryProps, EditorErrorBoundaryState> {\n override state: EditorErrorBoundaryState = { failed: false };\n\n static getDerivedStateFromError(): EditorErrorBoundaryState {\n return { failed: true };\n }\n\n override componentDidCatch(error: unknown, info: ErrorInfo) {\n logError(error, `custom editor ${this.props.editorId} crashed${info.componentStack ?? ''}`);\n }\n\n override render() {\n return this.state.failed ? this.props.fallback : this.props.children;\n }\n}\n","import { Suspense } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Skeleton } from '@/components/ui/skeleton';\nimport type { FieldControlState } from '../hooks/useFieldControl';\nimport { EditorErrorBoundary } from '../runtime/EditorErrorBoundary';\n\ntype FieldEditorProps = { control: FieldControlState };\n\n/**\n * The editor a field resolves to: a project's custom editor (falling back to the built-in if it throws) or\n * a built-in one (lazy ones show a skeleton while they load), plus the note when a custom editor is missing.\n */\nexport const FieldEditor = ({ control }: FieldEditorProps) => {\n const { t } = useTranslation();\n const { resolved, builtIn, builtInProps, contractProps } = control;\n const BuiltInComponent = builtIn.component;\n return (\n <>\n {resolved.kind === 'runtime' ? (\n <EditorErrorBoundary\n editorId={resolved.definition.id}\n fallback={<BuiltInComponent {...builtInProps} />}\n >\n <resolved.definition.component {...contractProps} />\n </EditorErrorBoundary>\n ) : (\n <Suspense fallback={<Skeleton className=\"h-24 w-full\" />}>\n <BuiltInComponent {...builtInProps} />\n </Suspense>\n )}\n {resolved.kind === 'builtIn' && resolved.missingCustomId ? (\n <p className=\"text-meta text-muted-foreground\">\n {t('content.fields.customEditorMissing', { id: resolved.missingCustomId })}\n </p>\n ) : null}\n </>\n );\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport type { FieldControlState } from '../hooks/useFieldControl';\n\ntype FieldMessagesProps = { field: FieldDefinition; control: FieldControlState };\n\n/** A field's description (written by the model's author, always visible) and its inline errors. */\nexport const FieldMessages = ({ field, control }: FieldMessagesProps) => (\n <>\n {field.description ? (\n <p id={control.descriptionId} className=\"text-meta text-muted-foreground\">\n {field.description}\n </p>\n ) : null}\n {control.messages.length > 0 ? (\n <ul id={control.errorsId} className=\"space-y-0.5 text-meta font-medium text-destructive\">\n {control.messages.map((message) => (\n <li key={message}>{message}</li>\n ))}\n </ul>\n ) : null}\n </>\n);\n","import type { ContentIssue } from '@shapio/client';\nimport {\n BIGINTEGER_PATTERN,\n DATE_PATTERN,\n DATETIME_PATTERN,\n DECIMAL_PATTERN,\n SLUG_PATTERN,\n TIME_PATTERN,\n UID_PATTERN,\n type FieldDefinition,\n} from '@shapio/schema';\nimport { isEmptyValue, toList } from './values';\n\n/**\n * Checks the admin runs while someone types, so obvious mistakes show before saving. The server is the\n * enforcement layer (CONTRIBUTING.md rule 5) and runs the full validator on every save; these only mirror the\n * cheap, local rules (format, length, range, counts). `required` is left to the server, which skips it on\n * autosave by design.\n */\ntype ClientIssue = Pick<ContentIssue, 'code' | 'message'>;\n\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nconst URL_PATTERN = /^(https?:\\/\\/[^\\s]+|mailto:[^\\s]+|tel:[^\\s]+)$/i;\n\nconst PATTERNS: Partial<Record<FieldDefinition['type'], RegExp>> = {\n email: EMAIL_PATTERN,\n url: URL_PATTERN,\n slug: SLUG_PATTERN,\n uid: UID_PATTERN,\n date: DATE_PATTERN,\n datetime: DATETIME_PATTERN,\n time: TIME_PATTERN,\n decimal: DECIMAL_PATTERN,\n biginteger: BIGINTEGER_PATTERN,\n};\n\nconst issue = (code: string): ClientIssue => ({ code, message: code });\n\nconst checkLength = (text: string, settings: { minLength?: number; maxLength?: number }): ClientIssue[] => [\n ...(settings.minLength !== undefined && text.length < settings.minLength ? [issue('TOO_SHORT')] : []),\n ...(settings.maxLength !== undefined && text.length > settings.maxLength ? [issue('TOO_LONG')] : []),\n];\n\nconst checkRange = (value: number, settings: { min?: number | string; max?: number | string }) => [\n ...(settings.min !== undefined && value < Number(settings.min) ? [issue('TOO_SMALL')] : []),\n ...(settings.max !== undefined && value > Number(settings.max) ? [issue('TOO_LARGE')] : []),\n];\n\nconst checkCount = (count: number, settings: { min?: number; max?: number }) => [\n ...(settings.min !== undefined && count > 0 && count < settings.min ? [issue('TOO_FEW')] : []),\n ...(settings.max !== undefined && count > settings.max ? [issue('TOO_MANY')] : []),\n];\n\nconst parsesAsJson = (text: string) => {\n try {\n JSON.parse(text);\n return true;\n } catch {\n return false;\n }\n};\n\n/** Code is never changed or trimmed; with `validate` on (JSON only) it must parse. */\nconst checkCode = (text: string, settings: { language: string; validate?: boolean | undefined }) =>\n settings.validate === true && settings.language === 'json' && !parsesAsJson(text)\n ? [issue('INVALID_FORMAT')]\n : [];\n\nconst checkText = (field: FieldDefinition, text: string): ClientIssue[] => {\n const pattern = PATTERNS[field.type];\n if (pattern && !pattern.test(text)) {\n return [issue('INVALID_FORMAT')];\n }\n switch (field.type) {\n case 'string':\n case 'text':\n case 'slug':\n case 'uid':\n return checkLength(text, field.settings);\n case 'code':\n return [...checkCode(text, field.settings), ...checkLength(text, field.settings)];\n case 'decimal':\n case 'biginteger':\n return checkRange(Number(text), field.settings);\n case 'enum':\n return field.settings.values.some((option) => option.value === text) ? [] : [issue('NOT_ALLOWED')];\n default:\n return [];\n }\n};\n\nexport const clientIssuesOf = (field: FieldDefinition, value: unknown): ClientIssue[] => {\n if (isEmptyValue(value)) {\n return [];\n }\n switch (field.type) {\n case 'number':\n case 'integer':\n if (typeof value !== 'number' || Number.isNaN(value)) {\n return [issue('INVALID_TYPE')];\n }\n return field.type === 'integer' && !Number.isInteger(value)\n ? [issue('INVALID_TYPE')]\n : checkRange(value, field.settings);\n case 'media':\n case 'relation':\n case 'component':\n case 'dynamiczone':\n return checkCount(toList(value).length, field.settings);\n default:\n return typeof value === 'string' ? checkText(field, value) : [];\n }\n};\n","/** The DOM id of a field's control: unique per form (`prefix`) and value path (`/hero/title`). */\nexport const fieldDomId = (prefix: string, path: string) =>\n `${prefix}field${path.replace(/[^A-Za-z0-9_-]/g, '-')}`;\n","import type { EditorContext, EditorField, EditorModel } from '@shapio/editor-sdk';\nimport type { FieldDefinition, SchemaDefinition } from '@shapio/schema';\nimport { i18next } from '@/app/i18n';\nimport type { FieldsEnvironment } from '../form/context';\n\n/** The editor contract's view of a field: metadata only, nothing an editor could use to reach the backend. */\nexport const toEditorField = (field: FieldDefinition): EditorField => ({\n id: field.id,\n apiKey: field.apiKey,\n label: field.label,\n description: field.description,\n type: field.type,\n required: field.required,\n localized: field.localized,\n settings: field.settings,\n options: field.editor.options,\n});\n\nexport const toEditorModel = (definition: SchemaDefinition): EditorModel => ({\n id: definition.id,\n apiKey: definition.apiKey,\n label: definition.label,\n kind: definition.kind,\n localized: definition.kind === 'component' ? false : definition.localized,\n});\n\nconst interpolate = (text: string, values: Readonly<Record<string, string | number>> | undefined) =>\n values\n ? text.replace(/\\{\\{\\s*(\\w+)\\s*\\}\\}/g, (match, name: string) => String(values[name] ?? match))\n : text;\n\n/** Custom editors ask for keys by name at runtime, so this lookup is untyped by design. */\nconst translateKey = i18next.t.bind(i18next) as unknown as (\n key: string,\n values?: Readonly<Record<string, string | number>>,\n) => string;\n\n/** The limited capabilities an editor gets (ADR 0009): locale, entry, media picking, translation. */\nexport const toEditorContext = (environment: FieldsEnvironment): EditorContext => ({\n locale: environment.locale,\n entryId: environment.entryId,\n uiLanguage: i18next.language,\n pickMedia: environment.pickMedia,\n translate: (key, fallback, values) =>\n i18next.exists(key) ? translateKey(key, values) : interpolate(fallback, values),\n});\n","import type { ContentIssue } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { i18next } from '@/app/i18n';\n\n/**\n * Validation issues (the server's 422 CONTENT_INVALID `details.issues`, and the admin's own client-side\n * checks) keyed by JSON pointer in API keys, e.g. `/sections/0/title`, the same paths the form uses.\n */\nexport type IssueMap = ReadonlyMap<string, readonly ContentIssue[]>;\n\n/** RFC 6901 pointer segment. API keys never need escaping, but component keys and indexes are appended. */\nexport const pointerOf = (base: string, segment: string | number) =>\n `${base}/${String(segment).replace(/~/g, '~0').replace(/\\//g, '~1')}`;\n\nexport const issuesByPath = (issues: readonly ContentIssue[]): IssueMap => {\n const map = new Map<string, ContentIssue[]>();\n for (const issue of issues) {\n map.set(issue.path, [...(map.get(issue.path) ?? []), issue]);\n }\n return map;\n};\n\n/** How many issues sit at or below a path (shown on collapsed items and section links). */\nexport const countIssuesUnder = (issues: IssueMap, path: string): number => {\n let count = 0;\n for (const [key, list] of issues) {\n if (key === path || key.startsWith(`${path}/`)) {\n count += list.length;\n }\n }\n return count;\n};\n\nconst FORMAT_KEYS = {\n email: 'content.issues.format.email',\n url: 'content.issues.format.url',\n slug: 'content.issues.format.slug',\n uid: 'content.issues.format.uid',\n date: 'content.issues.format.date',\n datetime: 'content.issues.format.datetime',\n time: 'content.issues.format.time',\n decimal: 'content.issues.format.decimal',\n biginteger: 'content.issues.format.biginteger',\n code: 'content.issues.format.code',\n} as const;\n\ntype CountKey =\n | 'content.issues.tooShort'\n | 'content.issues.tooLong'\n | 'content.issues.tooSmall'\n | 'content.issues.tooLarge'\n | 'content.issues.tooFew'\n | 'content.issues.tooMany';\n\nconst hasFormatKey = (type: string): type is keyof typeof FORMAT_KEYS => Object.hasOwn(FORMAT_KEYS, type);\n\nconst setting = (field: FieldDefinition | undefined, key: string): string | number | undefined => {\n const value = (field?.settings as Record<string, unknown> | undefined)?.[key];\n return typeof value === 'number' || typeof value === 'string' ? value : undefined;\n};\n\n/** A translated message for an issue. Without the numbers a message needs, the server's text is used. */\nexport const describeIssue = (\n issue: Pick<ContentIssue, 'code' | 'message'>,\n field?: FieldDefinition,\n): string => {\n const t = i18next.t.bind(i18next);\n const withCount = (key: CountKey, settingKey: string) => {\n const count = setting(field, settingKey);\n return count === undefined ? issue.message : t(key, { count: Number(count), value: String(count) });\n };\n switch (issue.code) {\n case 'REQUIRED':\n return t('content.issues.required');\n case 'INVALID_TYPE':\n return t('content.issues.invalidType');\n case 'INVALID_FORMAT':\n return field && hasFormatKey(field.type)\n ? t(FORMAT_KEYS[field.type])\n : t('content.issues.invalidFormat');\n case 'TOO_SHORT':\n return withCount('content.issues.tooShort', 'minLength');\n case 'TOO_LONG':\n return withCount('content.issues.tooLong', 'maxLength');\n case 'TOO_SMALL':\n return withCount('content.issues.tooSmall', 'min');\n case 'TOO_LARGE':\n return withCount('content.issues.tooLarge', 'max');\n case 'TOO_FEW':\n return withCount('content.issues.tooFew', 'min');\n case 'TOO_MANY':\n return withCount('content.issues.tooMany', 'max');\n case 'NOT_ALLOWED':\n return t('content.issues.notAllowed');\n case 'PATTERN_MISMATCH':\n return t('content.issues.patternMismatch');\n case 'DUPLICATE':\n return t('content.issues.duplicate');\n case 'UNKNOWN_FIELD':\n return t('content.issues.unknownField');\n case 'UNKNOWN_COMPONENT':\n return t('content.issues.unknownComponent');\n case 'INVALID_RICHTEXT':\n return t('content.issues.invalidRichText');\n case 'NOT_UNIQUE':\n return t('content.issues.notUnique');\n case 'RELATION_TARGET_MISSING':\n return t('content.issues.relationMissing');\n case 'MEDIA_MISSING':\n return t('content.issues.mediaMissing');\n case 'INVALID_JSON':\n return t('content.issues.invalidJson');\n default:\n return issue.message;\n }\n};\n","import { i18next } from '@/app/i18n';\nimport type { BuiltInEditorProps } from '../types';\nimport { stringOption } from './props';\n\nexport type Choice = { value: string; label: string };\n\n/** The choices of an enum (labels are content, shown as authored) or a boolean (Yes/No or custom labels). */\nexport const choicesOf = (props: BuiltInEditorProps): Choice[] => {\n const { definition } = props;\n if (definition.type === 'enum') {\n return definition.settings.values.map(({ value, label }) => ({ value, label }));\n }\n return [\n { value: 'true', label: stringOption(props, 'trueLabel') ?? i18next.t('content.fields.yes') },\n { value: 'false', label: stringOption(props, 'falseLabel') ?? i18next.t('content.fields.no') },\n ];\n};\n\n/** Choice value (always a string in the control) → field value. */\nexport const fromChoice = (props: BuiltInEditorProps, choice: string): unknown => {\n if (choice === '') {\n return null;\n }\n return props.definition.type === 'boolean' ? choice === 'true' : choice;\n};\n\nexport const toChoice = (value: unknown): string =>\n typeof value === 'boolean' ? String(value) : typeof value === 'string' ? value : '';\n\nexport const isMultiple = (props: BuiltInEditorProps) =>\n props.definition.type === 'enum' && props.definition.settings.multiple;\n","import { Checkbox } from '@/components/ui/checkbox';\nimport { Label } from '@/components/ui/label';\nimport { cn } from '@/helpers/cn';\nimport { choicesOf } from '../helpers/choices';\nimport { stringOption } from '../helpers/props';\nimport { toList } from '../helpers/values';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `checkboxGroup`: one checkbox per value of a multiple-choice enum. Values keep the enum's order. */\nexport const CheckboxGroup = (props: BuiltInEditorProps) => {\n const { inputId, labelId, describedBy, value, onChange, onBlur, readOnly, disabled, validation } = props;\n const selected = toList<string>(value);\n const choices = choicesOf(props);\n const horizontal = stringOption(props, 'layout') === 'horizontal';\n return (\n <div\n role=\"group\"\n aria-labelledby={labelId}\n aria-describedby={describedBy}\n aria-invalid={validation.invalid || undefined}\n className={cn('grid gap-2', horizontal && 'flex flex-wrap gap-x-6')}\n onBlur={onBlur}\n >\n {choices.map((choice) => (\n <div key={choice.value} className=\"flex items-center gap-2\">\n <Checkbox\n id={`${inputId}-${choice.value}`}\n checked={selected.includes(choice.value)}\n disabled={disabled || readOnly}\n onCheckedChange={(checked) => {\n const next = choices\n .map((item) => item.value)\n .filter((item) => (item === choice.value ? checked === true : selected.includes(item)));\n onChange(next.length > 0 ? next : null);\n }}\n />\n <Label htmlFor={`${inputId}-${choice.value}`} className=\"font-normal\">\n {choice.label}\n </Label>\n </div>\n ))}\n </div>\n );\n};\n","import { Checkbox } from '@/components/ui/checkbox';\nimport { inputAria } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `checkbox`: a checkbox for booleans. */\nexport const CheckboxInput = (props: BuiltInEditorProps) => {\n const { value, onChange, onBlur, readOnly, disabled } = props;\n return (\n <Checkbox\n {...inputAria(props)}\n checked={value === true}\n disabled={disabled || readOnly}\n onCheckedChange={(checked) => onChange(checked === true)}\n onBlur={onBlur}\n />\n );\n};\n","import type { CSSProperties } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Input } from '@/components/ui/input';\nimport { cn } from '@/helpers/cn';\nimport { inputAria, textValue } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\nconst HEX_COLOUR = /^#[0-9a-f]{6}$/i;\n/** The native picker needs some value when the field is empty or not hex; black, built so no hex literal appears. */\nconst EMPTY_PICKER_VALUE = `#${'0'.repeat(6)}`;\n\nconst presetsOf = (props: BuiltInEditorProps): string[] => {\n const presets = props.field.options.presets;\n return Array.isArray(presets)\n ? presets.filter((preset): preset is string => typeof preset === 'string')\n : [];\n};\n\n/** A swatch shows a user-chosen colour: the one dynamic value, passed through a CSS variable. */\nconst swatchStyle = (colour: string) => ({ '--swatch': colour }) as CSSProperties;\n\n/** `color`: a colour stored as text (hex or `rgb(…)`), with a picker and the field's preset swatches. */\nexport const ColorInput = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { value, onChange, onBlur, readOnly, disabled, field } = props;\n const text = textValue(value);\n const presets = presetsOf(props);\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <input\n type=\"color\"\n aria-label={t('content.fields.color.picker', { field: field.label })}\n value={HEX_COLOUR.test(text) ? text.toLowerCase() : EMPTY_PICKER_VALUE}\n disabled={disabled || readOnly}\n className=\"size-10 shrink-0 cursor-pointer rounded-lg border border-input bg-transparent p-1 disabled:cursor-not-allowed\"\n onChange={(event) => onChange(event.target.value)}\n />\n <Input\n {...inputAria(props)}\n value={text}\n spellCheck={false}\n readOnly={readOnly}\n disabled={disabled}\n className=\"max-w-48 font-mono text-sm\"\n onChange={(event) => onChange(event.target.value === '' ? null : event.target.value)}\n onBlur={onBlur}\n />\n </div>\n {presets.length > 0 ? (\n <div role=\"group\" aria-label={t('content.fields.color.presets')} className=\"flex flex-wrap gap-1.5\">\n {presets.map((preset) => (\n <button\n key={preset}\n type=\"button\"\n aria-label={preset}\n aria-pressed={preset.toLowerCase() === text.toLowerCase()}\n disabled={disabled || readOnly}\n style={swatchStyle(preset)}\n className={cn(\n 'size-7 rounded-md border border-input bg-(--swatch) outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n preset.toLowerCase() === text.toLowerCase() &&\n 'ring-2 ring-ring ring-offset-2 ring-offset-background',\n )}\n onClick={() => onChange(preset)}\n />\n ))}\n </div>\n ) : null}\n </div>\n );\n};\n","import { Plus } from 'lucide-react';\nimport type { ComponentProps } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/helpers/cn';\n\ntype AddItemButtonProps = Omit<ComponentProps<typeof Button>, 'children' | 'size' | 'variant'> & {\n /** \"Add Text item\", \"Add section\". */\n label: string;\n /** `outline` in forms and empty states; `ghost` at the end of a canvas list, like the canvas's own `+`. */\n variant?: 'outline' | 'ghost';\n};\n\n/**\n * Adds to a list (or fills an empty single component). Passes its other props to the button, so it can be\n * a menu's trigger (`asChild`).\n */\nexport const AddItemButton = ({ label, variant = 'outline', className, ...props }: AddItemButtonProps) => (\n <Button\n type=\"button\"\n variant={variant}\n size=\"sm\"\n className={cn(variant === 'ghost' && '-ml-2 text-muted-foreground', className)}\n {...props}\n >\n <Plus aria-hidden=\"true\" />\n {label}\n </Button>\n);\n","import { Globe, Languages } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { cn } from '@/helpers/cn';\n\ntype ScopeBadgeProps = { localized: boolean };\n\nconst CHIP_CLASSES =\n 'inline-flex h-5 items-center gap-1 rounded-full px-2 text-2xs font-semibold [&_svg]:size-3 [&_svg]:shrink-0';\n\n/**\n * In a localized model, says whether a field is per locale or shared by every locale of the entry. Shared\n * fields explain themselves on click (saving one changes every locale's draft, ADR 0004).\n */\nexport const ScopeBadge = ({ localized }: ScopeBadgeProps) => {\n const { t } = useTranslation();\n if (localized) {\n return (\n <span className={cn(CHIP_CLASSES, 'bg-accent text-accent-foreground')}>\n <Languages aria-hidden=\"true\" />\n {t('content.scope.localized')}\n </span>\n );\n }\n return (\n <Popover>\n <PopoverTrigger\n type=\"button\"\n className={cn(\n CHIP_CLASSES,\n 'border text-muted-foreground outline-none hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50',\n )}\n >\n <Globe aria-hidden=\"true\" />\n {t('content.scope.shared')}\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 p-3 text-meta\">\n {t('content.scope.sharedHint')}\n </PopoverContent>\n </Popover>\n );\n};\n","import { Globe, Languages } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { cn } from '@/helpers/cn';\n\ntype ScopeIconProps = { localized: boolean; className?: string };\n\n/**\n * The document's quiet version of `ScopeBadge`: a 14px icon saying whether a value is per locale or shared\n * by every locale (ADR 0004). Its name is in a tooltip and in text for screen readers.\n */\nexport const ScopeIcon = ({ localized, className }: ScopeIconProps) => {\n const { t } = useTranslation();\n const Icon = localized ? Languages : Globe;\n const label = localized ? t('content.scope.localized') : t('content.scope.sharedHint');\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n className={cn('inline-flex shrink-0 text-muted-foreground [&_svg]:size-3.5', className)}\n data-scope={localized ? 'localized' : 'shared'}\n >\n <Icon aria-hidden=\"true\" />\n <span className=\"sr-only\">{label}</span>\n </span>\n </TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n );\n};\n","import type { FieldDefinition, SchemaDefinition } from '@shapio/schema';\nimport { memo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Label } from '@/components/ui/label';\nimport { cn } from '@/helpers/cn';\nimport { FieldEditor } from '../FieldEditor';\nimport { FieldMessages } from '../FieldMessages';\nimport { useFieldsEnvironment } from '../form/context';\nimport { useFieldControl } from '../hooks/useFieldControl';\nimport { ScopeBadge } from '../ScopeBadge';\nimport { ScopeIcon } from '../ScopeIcon';\n\nexport type FieldLayout = 'stacked' | 'inline' | 'bare';\n\ntype FieldControlProps = {\n field: FieldDefinition;\n /** The model or component the field belongs to. */\n owner: SchemaDefinition;\n value: unknown;\n onChange: (value: unknown) => void;\n /** JSON pointer of the value, e.g. `/hero/title` (issues use the same paths). */\n path: string;\n /** A field of the entry itself (shows the localized/shared badge in localized models). */\n topLevel: boolean;\n /**\n * `stacked` (default): label above the editor (forms, the settings drawer). `inline`: a small label beside\n * the value, a line of a document (the property grid, component blocks in the canvas). `bare`: the\n * label only names the control (the settings drawer's row already shows it).\n */\n layout?: FieldLayout;\n className?: string;\n};\n\n/**\n * One field in a form: label (with the localized/shared badge), the editor the field's definition chooses,\n * help text and inline errors.\n */\nexport const FieldControl = memo(\n ({ field, owner, value, onChange, path, topLevel, layout = 'stacked', className }: FieldControlProps) => {\n const { t } = useTranslation();\n const environment = useFieldsEnvironment();\n const control = useFieldControl({ field, owner, value, onChange, path });\n const LabelElement = control.labelling === 'input' ? Label : 'span';\n const inline = layout === 'inline';\n return (\n <div\n className={cn(\n 'min-w-0 scroll-mt-24',\n inline ? 'grid gap-x-4 gap-y-1 sm:grid-cols-[9rem_minmax(0,1fr)]' : 'space-y-2',\n className,\n )}\n id={`${control.inputId}-section`}\n data-field-path={path}\n >\n <div\n className={cn(\n 'flex min-h-5 flex-wrap items-center gap-2',\n inline && 'sm:min-h-10 sm:pt-0.5',\n layout === 'bare' && 'sr-only',\n )}\n >\n <LabelElement\n id={control.labelId}\n {...(control.labelling === 'input' ? { htmlFor: control.inputId } : {})}\n className={cn(\n 'leading-5',\n inline ? 'text-meta font-medium text-muted-foreground' : 'text-sm font-semibold',\n )}\n >\n {field.label}\n {field.required ? (\n <>\n <span aria-hidden=\"true\" className=\"ml-0.5 text-destructive\">\n *\n </span>\n <span className=\"sr-only\">{t('content.fields.required')}</span>\n </>\n ) : null}\n </LabelElement>\n {topLevel && environment.model.localized ? (\n inline ? (\n <ScopeIcon localized={field.localized} />\n ) : (\n <ScopeBadge localized={field.localized} />\n )\n ) : null}\n </div>\n <div className=\"min-w-0 space-y-2\">\n <FieldEditor control={control} />\n <FieldMessages field={field} control={control} />\n </div>\n </div>\n );\n },\n);\n\nFieldControl.displayName = 'FieldControl';\n","import { entryLayoutOf, type FieldWidth, type ModelDefinition } from '@shapio/schema';\n\n/**\n * The six-column grid a form-layout entry lays its fields on (`FieldGrid` in width mode). A container query,\n * not a viewport breakpoint: below `@lg` (32rem) of the form column every field takes the whole row. `@lg`\n * keeps the row with the settings drawer open on a 1440px screen, where the column is about 630px wide.\n */\nexport const WIDTH_GRID_CLASSES = 'grid gap-5 @lg:grid-cols-6';\n\n/** How many of the grid's six columns a field spans at each `FieldWidth`. Full class strings, never built. */\nexport const WIDTH_CLASSES = {\n full: '@lg:col-span-6',\n 'two-thirds': '@lg:col-span-4',\n half: '@lg:col-span-3',\n third: '@lg:col-span-2',\n} as const satisfies Record<FieldWidth, string>;\n\n/** The span classes of a field's width; unset is `full`. */\nexport const widthClassOf = (width: FieldWidth | undefined): string => WIDTH_CLASSES[width ?? 'full'];\n\n/**\n * How `FieldGrid` lays out a model's own fields: `compact` pairs short values up automatically (component\n * items, quick edit, a document-layout model); `widths` spans each field by its `width` (a form-layout model).\n */\nexport type FieldGridMode = 'compact' | 'widths';\n\n/** The grid mode for an entry's own fields: `widths` when the model opens as a form. */\nexport const fieldGridModeOf = (model: ModelDefinition): FieldGridMode =>\n entryLayoutOf(model) === 'form' ? 'widths' : 'compact';\n","import type { FieldDefinition } from '@shapio/schema';\nimport type { ReactNode } from 'react';\nimport { WIDTH_GRID_CLASSES, widthClassOf, type FieldGridMode } from '../helpers/widthClasses';\n\ntype FieldGridProps = {\n fields: readonly FieldDefinition[];\n renderField: (field: FieldDefinition, className: string) => ReactNode;\n /** `compact` (default) or `widths`; see `FieldGridMode`. */\n mode?: FieldGridMode;\n};\n\n/**\n * Short values sit two to a row when the form column itself is wide (title + slug, like the mockup); the\n * rest span the row. A container query, not a viewport breakpoint: the entry form's centre column sits\n * between two side panels, and splitting it on a wide screen left inputs a third of the column wide.\n */\nconst COMPACT_TYPES: ReadonlySet<string> = new Set([\n 'string',\n 'slug',\n 'email',\n 'url',\n 'uid',\n 'number',\n 'integer',\n 'decimal',\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'time',\n]);\n\nconst isCompact = (field: FieldDefinition) =>\n COMPACT_TYPES.has(field.type) || (field.type === 'enum' && field.editor.id === 'select');\n\nexport const FieldGrid = ({ fields, renderField, mode = 'compact' }: FieldGridProps) => (\n <div className=\"@container\">\n {mode === 'widths' ? (\n <div className={WIDTH_GRID_CLASSES}>\n {fields.map((field) => renderField(field, widthClassOf(field.width)))}\n </div>\n ) : (\n <div className=\"grid gap-5 @2xl:grid-cols-2\">\n {fields.map((field) => renderField(field, isCompact(field) ? '@2xl:col-span-1' : '@2xl:col-span-2'))}\n </div>\n )}\n </div>\n);\n","import type { MediaAsset } from '@shapio/client';\nimport type { ComponentDefinition, FieldDefinition } from '@shapio/schema';\nimport {\n COMPONENT_KEY,\n isEmptyValue,\n isRecord,\n isSameContent,\n stripClientKeys,\n withClientKey,\n type FormValues,\n type ItemValues,\n} from './values';\n\n/**\n * Conversion between the admin API's entry data and the form's values. Reads return media fields as asset\n * views (`{ id, url, ... }`); the form and every write use asset IDs, so editors (custom ones included)\n * always see the same value the server validates.\n */\nexport type ComponentLookup = ReadonlyMap<string, ComponentDefinition>;\n\ntype Collect = (asset: MediaAsset) => void;\n\nconst isAssetView = (value: unknown): value is MediaAsset =>\n isRecord(value) && typeof value.id === 'string' && typeof value.url === 'string';\n\nconst mediaIdOf = (value: unknown, collect: Collect | undefined): string | null => {\n if (typeof value === 'string') {\n return value;\n }\n if (isAssetView(value)) {\n collect?.(value);\n return value.id;\n }\n return null;\n};\n\nexport const liveFields = (fields: readonly FieldDefinition[]) => fields.filter((field) => !field.deprecated);\n\nconst componentOfItem = (\n field: FieldDefinition<'dynamiczone'>,\n item: ItemValues,\n components: ComponentLookup,\n): ComponentDefinition | undefined =>\n field.settings.components\n .map((id) => components.get(id))\n .find((component) => component?.apiKey === item[COMPONENT_KEY]);\n\nconst fromApiValue = (\n field: FieldDefinition,\n value: unknown,\n components: ComponentLookup,\n collect: Collect | undefined,\n): unknown => {\n if (value === undefined || value === null) {\n return null;\n }\n switch (field.type) {\n case 'media':\n return Array.isArray(value)\n ? value.map((item) => mediaIdOf(item, collect)).filter((id): id is string => id !== null)\n : mediaIdOf(value, collect);\n case 'component': {\n const component = components.get(field.settings.component);\n const convert = (item: unknown) =>\n withClientKey(\n component && isRecord(item) ? toFormValues(component.fields, item, components, collect) : {},\n );\n return field.settings.repeatable ? (Array.isArray(value) ? value.map(convert) : []) : convert(value);\n }\n case 'dynamiczone':\n return (Array.isArray(value) ? value : []).filter(isRecord).map((item) => {\n const component = componentOfItem(field, item, components);\n return withClientKey({\n [COMPONENT_KEY]: item[COMPONENT_KEY],\n ...(component ? toFormValues(component.fields, item, components, collect) : {}),\n });\n });\n default:\n return value;\n }\n};\n\n/** API data (one model or component level) → form values. `collect` receives every media asset view seen. */\nexport function toFormValues(\n fields: readonly FieldDefinition[],\n data: Readonly<Record<string, unknown>>,\n components: ComponentLookup,\n collect?: Collect,\n): FormValues {\n const values: FormValues = {};\n for (const field of liveFields(fields)) {\n values[field.apiKey] = fromApiValue(field, data[field.apiKey], components, collect);\n }\n return values;\n}\n\n/** Initial values for a new entry or component item: each field's default, or empty. */\nexport const defaultFormValues = (fields: readonly FieldDefinition[]): FormValues =>\n Object.fromEntries(\n liveFields(fields).map((field) => [field.apiKey, structuredClone(field.defaultValue ?? null) as unknown]),\n );\n\nexport const newComponentItem = (component: ComponentDefinition, zoned: boolean): ItemValues =>\n withClientKey({\n ...(zoned ? { [COMPONENT_KEY]: component.apiKey } : {}),\n ...defaultFormValues(component.fields),\n });\n\n/** A form value as the API takes it: client keys stripped, empty values sent as null (= clear). */\nexport const toInputValue = (value: unknown): unknown =>\n isEmptyValue(value) ? null : stripClientKeys(value);\n\n/** Top-level API keys whose value differs from the baseline (what the last load or save returned). */\nexport const dirtyKeysOf = (values: FormValues, baseline: FormValues): string[] =>\n Object.keys(values).filter((key) => !isSameContent(values[key], baseline[key]));\n\n/** The PUT body's `data`: changed fields only (the API treats it as a patch). */\nexport const buildPatch = (values: FormValues, keys: readonly string[]): Record<string, unknown> =>\n Object.fromEntries(keys.map((key) => [key, toInputValue(values[key])]));\n\n/** Every non-empty value, for creating an entry. */\nexport const buildCreateData = (values: FormValues): Record<string, unknown> =>\n Object.fromEntries(\n Object.entries(values)\n .filter(([, value]) => !isEmptyValue(value))\n .map(([key, value]) => [key, stripClientKeys(value)]),\n );\n\n/**\n * After a save: the server's values become the baseline. Fields the person did not touch while the save\n * was in flight take the server's (canonical) value, keeping the current object when the content is the\n * same so list items keep their client keys; fields edited meanwhile keep the newer local value.\n */\nexport const mergeSaved = (\n current: FormValues,\n sent: FormValues,\n saved: FormValues,\n): { values: FormValues; baseline: FormValues } => {\n const values: FormValues = { ...current };\n const baseline: FormValues = { ...saved };\n for (const key of Object.keys(saved)) {\n const editedMeanwhile = !Object.is(current[key], sent[key]);\n if (editedMeanwhile) {\n continue;\n }\n if (isSameContent(current[key], saved[key])) {\n baseline[key] = current[key];\n } else {\n values[key] = saved[key];\n }\n }\n return { values, baseline };\n};\n","import type { ComponentDefinition, FieldDefinition } from '@shapio/schema';\nimport { useMemo, type ReactNode } from 'react';\nimport { cn } from '@/helpers/cn';\nimport { FieldControl } from '../FieldControl';\nimport { FieldGrid } from '../FieldGrid';\nimport { SiblingValuesContext } from '../form/context';\nimport { liveFields } from '../helpers/formValues';\nimport { pointerOf } from '../helpers/issues';\nimport type { ItemValues } from '../helpers/values';\n\ntype ComponentItemFieldsProps = {\n component: ComponentDefinition;\n item: ItemValues;\n onItemChange: (item: ItemValues) => void;\n /** Pointer of the item, e.g. `/hero` or `/sections/2`. */\n path: string;\n /** `document`: label + value lines, as a component block in the entry canvas. */\n layout?: 'form' | 'document';\n /** Extra content under a field (the SEO editor's length counters), keyed on the field's stable ID. */\n renderFieldFooter?: (field: FieldDefinition, value: unknown) => ReactNode;\n};\n\n/** The fields of one component value (a single component, a repeatable item or a dynamic-zone item). */\nexport const ComponentItemFields = ({\n component,\n item,\n onItemChange,\n path,\n layout = 'form',\n renderFieldFooter,\n}: ComponentItemFieldsProps) => {\n const siblings = useMemo(() => ({ definition: component, values: item }), [component, item]);\n const fields = liveFields(component.fields);\n const renderField = (field: FieldDefinition, className?: string) => {\n // Always wrapped when footers are on: a footer appearing must not remount the control (focus would go).\n const wrapped = renderFieldFooter !== undefined;\n const control = (\n <FieldControl\n key={field.id}\n field={field}\n owner={component}\n value={item[field.apiKey]}\n onChange={(next) => onItemChange({ ...item, [field.apiKey]: next })}\n path={pointerOf(path, field.apiKey)}\n topLevel={false}\n layout={layout === 'document' ? 'inline' : 'stacked'}\n className={wrapped ? undefined : className}\n />\n );\n return wrapped ? (\n <div key={field.id} className={cn('min-w-0 space-y-1.5', className)}>\n {control}\n {renderFieldFooter(field, item[field.apiKey])}\n </div>\n ) : (\n control\n );\n };\n return (\n <SiblingValuesContext.Provider value={siblings}>\n {layout === 'document' ? (\n <div className=\"space-y-3\">{fields.map((field) => renderField(field))}</div>\n ) : (\n <FieldGrid fields={fields} renderField={renderField} />\n )}\n </SiblingValuesContext.Provider>\n );\n};\n","import { richTextPlainText, type ComponentDefinition, type FieldDefinition } from '@shapio/schema';\nimport { i18next } from '@/app/i18n';\nimport { valueLabel } from '@/features/Models/helpers/labels';\nimport { isEmptyValue, isRecord, toList } from './values';\n\n/**\n * A short, readable summary of a value for collapsed component items, dynamic-zone outlines, list cells\n * and revision diffs. Plain text only; never markup from the content.\n */\nconst MAX_SUMMARY = 80;\n\nconst truncate = (text: string) => (text.length > MAX_SUMMARY ? `${text.slice(0, MAX_SUMMARY - 1)}…` : text);\n\nexport const summarizeValue = (field: FieldDefinition, value: unknown): string => {\n if (isEmptyValue(value)) {\n return '';\n }\n switch (field.type) {\n case 'richtext':\n return truncate(richTextPlainText(value));\n case 'boolean':\n return value === true ? '✓' : '✗';\n case 'enum':\n return toList<string>(value)\n .map((item) => field.settings.values.find((option) => option.value === item)?.label ?? item)\n .join(', ');\n case 'json':\n return truncate(JSON.stringify(value));\n case 'code':\n // A snippet reads badly as a label: its language and size instead (\"HTML, 14 lines\").\n return i18next.t('content.fields.code.summary', {\n language: valueLabel(field.settings.language),\n count: String(value).split('\\n').length,\n });\n case 'media':\n case 'relation':\n case 'component':\n case 'dynamiczone':\n return String(toList(value).length);\n default:\n return truncate(String(value));\n }\n};\n\nconst TEXTUAL_TYPES: ReadonlySet<string> = new Set(['string', 'text', 'slug', 'email', 'url', 'uid', 'enum']);\n\n/** A component item's label: its title field's value, else the first non-empty text field. */\nexport const summarizeItem = (component: ComponentDefinition, item: unknown): string => {\n if (!isRecord(item)) {\n return '';\n }\n const titleField = component.fields.find((field) => field.id === component.display.titleFieldId);\n const candidates = titleField ? [titleField, ...component.fields] : component.fields;\n for (const field of candidates) {\n if (TEXTUAL_TYPES.has(field.type) || field.type === 'richtext') {\n const summary = summarizeValue(field, item[field.apiKey]);\n if (summary) {\n return summary;\n }\n }\n }\n return '';\n};\n","import { useCallback, useState } from 'react';\n\n/** Which list items are collapsed, by client key. New items are expanded; `startCollapsed` applies to loaded ones. */\nexport const useCollapsedItems = (initialKeys: readonly string[], startCollapsed: boolean) => {\n const [collapsed, setCollapsed] = useState<ReadonlySet<string>>(\n () => new Set(startCollapsed ? initialKeys : []),\n );\n const toggle = useCallback(\n (key: string) =>\n setCollapsed((current) => {\n const next = new Set(current);\n if (next.has(key)) {\n next.delete(key);\n } else {\n next.add(key);\n }\n return next;\n }),\n [],\n );\n const setAll = useCallback(\n (keys: readonly string[], value: boolean) => setCollapsed(new Set(value ? keys : [])),\n [],\n );\n return { collapsed, toggle, setAll };\n};\n","import { useEffect, useRef } from 'react';\n\n/** After an item is added, moves focus to its header so keyboard users land on what they created. */\nexport const useFocusNewItem = (keys: readonly string[], domId: (key: string) => string) => {\n const previous = useRef(keys);\n useEffect(() => {\n const added = keys.find((key) => !previous.current.includes(key));\n previous.current = keys;\n if (added && keys.length > 0) {\n document.getElementById(domId(added))?.querySelector<HTMLElement>('button[aria-expanded]')?.focus();\n }\n }, [keys, domId]);\n};\n","import { useState, type DragEvent } from 'react';\n\nconst DRAG_TYPE = 'application/x-shapio-item';\n\n/**\n * Native HTML5 drag to reorder the items of one list (component blocks in the canvas). Only drags that\n * started in this list are accepted, so files or other lists' items never drop here. ⌥↑ / ⌥↓ and the move\n * buttons do the same from the keyboard.\n */\nexport const useItemDrag = (move: (from: number, to: number) => void) => {\n const [from, setFrom] = useState<number | null>(null);\n const [over, setOver] = useState<number | null>(null);\n const reset = () => {\n setFrom(null);\n setOver(null);\n };\n return {\n handleProps: (index: number) => ({\n draggable: true,\n onDragStart: (event: DragEvent) => {\n setFrom(index);\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData(DRAG_TYPE, String(index));\n const item = (event.currentTarget as HTMLElement).closest('li');\n if (item) {\n event.dataTransfer.setDragImage(item, 16, 16);\n }\n },\n onDragEnd: reset,\n }),\n targetProps: (index: number) => ({\n onDragOver: (event: DragEvent) => {\n if (from === null || !event.dataTransfer.types.includes(DRAG_TYPE)) {\n return;\n }\n event.preventDefault();\n event.dataTransfer.dropEffect = 'move';\n setOver(index);\n },\n onDrop: (event: DragEvent) => {\n if (from === null) {\n return;\n }\n event.preventDefault();\n if (from !== index) {\n move(from, index);\n }\n reset();\n },\n }),\n /** Where the dragged item would land: before (moving up) or after (moving down) this item. */\n dropSide: (index: number): 'before' | 'after' | undefined =>\n from === null || over !== index || from === index ? undefined : from > index ? 'before' : 'after',\n };\n};\n","import { useMemo } from 'react';\nimport { useEntryForm } from '../form/context';\nimport { countIssuesUnder, issuesByPath } from '../helpers/issues';\n\n/** Server issues at or below a path (shown on collapsed items so problems are never hidden). */\nexport const useItemIssueCount = (path: string): number => {\n const issues = useEntryForm((state) => state.issues);\n return useMemo(() => countIssuesUnder(issuesByPath(issues), path), [issues, path]);\n};\n","import { ArrowDown, ArrowUp, ChevronRight, Copy, GripVertical, Trash2 } from 'lucide-react';\nimport type { DragEvent, KeyboardEvent, ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { StatusChip } from '@/components/StatusChip';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/helpers/cn';\n\ntype ItemCardProps = {\n id: string;\n title: string;\n summary: string;\n index: number;\n count: number;\n collapsed: boolean;\n issueCount: number;\n editable: boolean;\n onToggle: () => void;\n onMove?: (to: number) => void;\n onDuplicate?: () => void;\n onRemove?: () => void;\n /**\n * `canvas`: a block of the entry document: quiet chrome, actions on hover or focus, a drag grip.\n * Requires `drag` for the grip and the drop target.\n */\n appearance?: 'form' | 'canvas';\n drag?: {\n handle: { draggable: boolean; onDragStart: (event: DragEvent) => void; onDragEnd: () => void };\n target: { onDragOver: (event: DragEvent) => void; onDrop: (event: DragEvent) => void };\n dropSide: 'before' | 'after' | undefined;\n };\n children: ReactNode;\n};\n\n/**\n * One item of a repeatable component or dynamic zone: a header that collapses it (with a readable summary\n * and its problem count), move, duplicate and remove actions, and the item's fields. Alt+↑/↓ on the header\n * moves the item.\n */\nexport const ItemCard = ({\n id,\n title,\n summary,\n index,\n count,\n collapsed,\n issueCount,\n editable,\n onToggle,\n onMove,\n onDuplicate,\n onRemove,\n appearance = 'form',\n drag,\n children,\n}: ItemCardProps) => {\n const { t } = useTranslation();\n const bodyId = `${id}-body`;\n const onKeyDown = (event: KeyboardEvent) => {\n if (!event.altKey || !onMove) {\n return;\n }\n if (event.key === 'ArrowUp' && index > 0) {\n event.preventDefault();\n onMove(index - 1);\n } else if (event.key === 'ArrowDown' && index < count - 1) {\n event.preventDefault();\n onMove(index + 1);\n }\n };\n const canvas = appearance === 'canvas';\n // On the canvas the actions appear on hover, and stay while anything in the block has focus.\n const actionClasses = canvas\n ? 'opacity-0 transition-opacity group-focus-within/item:opacity-100 group-hover/item:opacity-100'\n : undefined;\n return (\n <li\n id={id}\n className={cn(\n 'group/item scroll-mt-32 rounded-xl border bg-card data-invalid:border-destructive/60',\n canvas && 'border-transparent bg-muted/40 focus-within:border-border hover:border-border',\n drag?.dropSide === 'before' && 'shadow-[0_-3px_0_0_var(--color-ring)]',\n drag?.dropSide === 'after' && 'shadow-[0_3px_0_0_var(--color-ring)]',\n )}\n data-invalid={issueCount > 0 || undefined}\n {...(canvas ? drag?.target : {})}\n >\n <div className=\"flex items-center gap-1 py-1.5 pr-2 pl-1.5\">\n {canvas && editable && drag ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n className={cn('cursor-grab text-muted-foreground active:cursor-grabbing', actionClasses)}\n aria-label={t('entry.blocks.dragItem', { item: title, position: index + 1 })}\n {...drag.handle}\n >\n <GripVertical aria-hidden=\"true\" />\n </Button>\n ) : null}\n <button\n type=\"button\"\n aria-expanded={!collapsed}\n aria-controls={bodyId}\n onClick={onToggle}\n onKeyDown={onKeyDown}\n className=\"flex h-8 min-w-0 flex-1 items-center gap-2 rounded-lg px-2 text-left outline-none hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n >\n <ChevronRight\n aria-hidden=\"true\"\n className={cn(\n 'size-4 shrink-0 text-muted-foreground transition-transform',\n !collapsed && 'rotate-90',\n )}\n />\n <span className=\"shrink-0 text-sm font-semibold\">{title}</span>\n {summary ? (\n <span className=\"min-w-0 truncate text-meta text-muted-foreground\">{summary}</span>\n ) : null}\n <span className=\"sr-only\">{t('content.items.position', { index: index + 1, count })}</span>\n </button>\n {issueCount > 0 ? (\n <StatusChip tone=\"danger\" size=\"sm\" label={t('content.items.problems', { count: issueCount })} />\n ) : null}\n <span className={cn('flex items-center gap-1', actionClasses)}>\n {editable && onMove ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.moveUp', { item: title, position: index + 1 })}\n disabled={index === 0}\n onClick={() => onMove(index - 1)}\n >\n <ArrowUp aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.moveDown', { item: title, position: index + 1 })}\n disabled={index === count - 1}\n onClick={() => onMove(index + 1)}\n >\n <ArrowDown aria-hidden=\"true\" />\n </Button>\n </>\n ) : null}\n {editable && onDuplicate ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.duplicate', { item: title, position: index + 1 })}\n onClick={onDuplicate}\n >\n <Copy aria-hidden=\"true\" />\n </Button>\n ) : null}\n {editable && onRemove ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.remove', { item: title, position: index + 1 })}\n onClick={onRemove}\n >\n <Trash2 aria-hidden=\"true\" />\n </Button>\n ) : null}\n </span>\n </div>\n <div id={bodyId} hidden={collapsed} className={cn(canvas ? 'px-4 pt-1 pb-4' : 'border-t p-5')}>\n {collapsed ? null : children}\n </div>\n </li>\n );\n};\n","import type { ComponentDefinition } from '@shapio/schema';\nimport { Boxes, Plus } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { useDeferredMenuAction } from '../hooks/useDeferredMenuAction';\nimport { InsertMenuItem } from '../InsertMenuItem';\n\ntype ItemInserterProps = {\n /** The components that can be stored here (a zone's allowed ones, or the repeatable's one). */\n components: readonly ComponentDefinition[];\n /** Where the new block goes, for its name (\"Add a block before item 2\"). */\n position: number;\n onInsert: (component: ComponentDefinition) => void;\n};\n\n/**\n * An insertion point between two component blocks of the canvas: a hairline with `+` that shows on hover\n * or keyboard focus and offers only what this list can hold.\n */\nexport const ItemInserter = ({ components, position, onInsert }: ItemInserterProps) => {\n const { t } = useTranslation();\n const menu = useDeferredMenuAction();\n return (\n <li className=\"group/inserter relative flex h-4 items-center\" data-item-inserter>\n <span\n aria-hidden=\"true\"\n className=\"h-px flex-1 bg-border opacity-0 transition-opacity group-focus-within/inserter:opacity-100 group-hover/inserter:opacity-100\"\n />\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon-xs\"\n className=\"absolute left-1/2 -translate-x-1/2 rounded-full bg-background opacity-0 transition-opacity group-hover/inserter:opacity-100 focus-visible:opacity-100 data-[state=open]:opacity-100\"\n aria-label={t('entry.blocks.insertAt', { position })}\n >\n <Plus aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"center\" className=\"w-72\" onCloseAutoFocus={menu.onCloseAutoFocus}>\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n {t('entry.blocks.groupComponents')}\n </DropdownMenuLabel>\n {components.map((component) => (\n <InsertMenuItem\n key={component.id}\n icon={Boxes}\n label={component.label}\n onSelect={() => menu.defer(() => onInsert(component))}\n />\n ))}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </li>\n );\n};\n","import type { ComponentDefinition } from '@shapio/schema';\nimport { Fragment, useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { ComponentItemFields } from '../ComponentItemFields';\nimport { pointerOf } from '../helpers/issues';\nimport { summarizeItem } from '../helpers/summary';\nimport { COMPONENT_KEY, type ItemValues } from '../helpers/values';\nimport { useCollapsedItems } from '../hooks/useCollapsedItems';\nimport { useFocusNewItem } from '../hooks/useFocusNewItem';\nimport { useItemDrag } from '../hooks/useItemDrag';\nimport { useItemIssueCount } from '../hooks/useItemIssueCount';\nimport type { useListEditor } from '../hooks/useListEditor';\nimport { ItemCard } from '../ItemCard';\nimport { ItemInserter } from '../ItemInserter';\n\ntype ListEditor = ReturnType<typeof useListEditor>;\n\ntype CanvasItemListProps = {\n list: ListEditor;\n labelId: string;\n inputId: string;\n path: string;\n editable: boolean;\n /** What can be inserted between blocks (empty when the list is full). */\n insertable: readonly ComponentDefinition[];\n /** The component an item is (a zone item's `__component`, or the repeatable's one). */\n componentOf: (item: ItemValues) => ComponentDefinition | undefined;\n newItem: (component: ComponentDefinition) => ItemValues;\n startCollapsed: boolean;\n};\n\ntype BlockProps = {\n list: ListEditor;\n item: ItemValues;\n itemKey: string;\n index: number;\n path: string;\n domId: string;\n editable: boolean;\n component: ComponentDefinition | undefined;\n collapsed: boolean;\n onToggle: (key: string) => void;\n drag: ReturnType<typeof useItemDrag>;\n};\n\nconst Block = ({\n list,\n item,\n itemKey,\n index,\n path,\n domId,\n editable,\n component,\n collapsed,\n onToggle,\n drag,\n}: BlockProps) => {\n const { t } = useTranslation();\n const itemPath = pointerOf(path, index);\n const issueCount = useItemIssueCount(itemPath);\n const onItemChange = useCallback((next: ItemValues) => list.update(index, next), [list, index]);\n return (\n <ItemCard\n id={domId}\n appearance=\"canvas\"\n title={component?.label ?? t('content.items.unknownComponent', { key: String(item[COMPONENT_KEY]) })}\n summary={component ? summarizeItem(component, item) : ''}\n index={index}\n count={list.items.length}\n collapsed={collapsed}\n issueCount={issueCount}\n editable={editable}\n onToggle={() => onToggle(itemKey)}\n onMove={(to) => list.move(index, to)}\n onDuplicate={component ? () => list.duplicate(index) : undefined}\n onRemove={() => list.remove(index)}\n drag={{\n handle: drag.handleProps(index),\n target: drag.targetProps(index),\n dropSide: drag.dropSide(index),\n }}\n >\n {component ? (\n <ComponentItemFields\n component={component}\n item={item}\n onItemChange={onItemChange}\n path={itemPath}\n layout=\"document\"\n />\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.items.unknownComponentHint')}</p>\n )}\n </ItemCard>\n );\n};\n\n/**\n * A dynamic zone or repeatable component as blocks of the entry canvas: each item a block with a compact\n * header (actions on hover), its fields as label + value lines, insertion points between blocks, and drag\n * (or ⌥↑↓) to reorder. Adding at the field's start or end is the canvas's boundary inserter.\n */\nexport const CanvasItemList = ({\n list,\n labelId,\n inputId,\n path,\n editable,\n insertable,\n componentOf,\n newItem,\n startCollapsed,\n}: CanvasItemListProps) => {\n const { collapsed, toggle } = useCollapsedItems(list.keys, startCollapsed);\n const domId = useCallback((key: string) => `${inputId}-item-${key}`, [inputId]);\n useFocusNewItem(list.keys, domId);\n const drag = useItemDrag(list.move);\n if (list.items.length === 0) {\n return null;\n }\n return (\n <ol aria-labelledby={labelId} className=\"space-y-1 font-sans\">\n {list.items.map((item, index) => {\n const key = list.keys[index] ?? String(index);\n return (\n <Fragment key={key}>\n {index > 0 && editable && insertable.length > 0 ? (\n <ItemInserter\n components={insertable}\n position={index + 1}\n onInsert={(component) => list.insertAt(index, newItem(component))}\n />\n ) : null}\n <Block\n list={list}\n item={item}\n itemKey={key}\n index={index}\n path={path}\n domId={domId(key)}\n editable={editable}\n component={componentOf(item)}\n collapsed={collapsed.has(key)}\n onToggle={toggle}\n drag={drag}\n />\n </Fragment>\n );\n })}\n </ol>\n );\n};\n","/** Whether a list of `count` items can take one more under its `max` (none: always). */\nexport const hasRoomFor = (count: number, max: number | undefined): boolean =>\n max === undefined || count < max;\n\n/**\n * The count an empty list must reach once it has items, when that changes what the person does: a `min`\n * of 2 or more means one item is not enough. A `min` of 1 says nothing (an empty optional list is valid,\n * and a required one already shows its asterisk), and `max` cannot matter while the list is empty.\n */\nexport const emptyListMinimum = (min: number | undefined): number | undefined =>\n min !== undefined && min > 1 ? min : undefined;\n","import { Boxes } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { EmptyState } from '@/components/EmptyState';\nimport { emptyListMinimum } from '../helpers/listLimits';\n\ntype EmptyListRowProps = {\n /** The list's `min`: named only when one item would not be enough. */\n min: number | undefined;\n /** How to add the first item (none when read-only or full). */\n action: ReactNode;\n};\n\n/** An empty list of the entry canvas: \"Nothing added yet.\" in a dashed row, with its add control. */\nexport const EmptyListRow = ({ min, action }: EmptyListRowProps) => {\n const { t } = useTranslation();\n const minimum = emptyListMinimum(min);\n return (\n <EmptyState\n compact\n icon={Boxes}\n title={t('content.items.empty')}\n description={minimum === undefined ? undefined : t('content.issues.tooFew', { count: minimum })}\n action={action}\n className=\"rounded-xl border border-dashed px-4\"\n />\n );\n};\n","import { useCallback } from 'react';\nimport { clientKeyOf, moveItem, toList, withClientKey, type ItemValues } from '../helpers/values';\n\n/** Add, insert, move, duplicate and remove for list values (repeatable components, dynamic zones). */\nexport const useListEditor = (value: unknown, onChange: (value: unknown) => void) => {\n const items = toList<ItemValues>(value);\n const commit = useCallback((next: ItemValues[]) => onChange(next.length > 0 ? next : null), [onChange]);\n return {\n items,\n keys: items.map((item, index) => clientKeyOf(item, index)),\n add: (item: ItemValues) => commit([...items, item]),\n /** Inserts before `index` (0 = first, `items.length` = last): the canvas's insertion points. */\n insertAt: (index: number, item: ItemValues) => {\n const at = Math.min(Math.max(index, 0), items.length);\n commit([...items.slice(0, at), item, ...items.slice(at)]);\n },\n update: (index: number, item: ItemValues) =>\n commit(items.map((current, at) => (at === index ? item : current))),\n move: (from: number, to: number) => commit(moveItem(items, from, to)),\n duplicate: (index: number) => {\n const copy = withClientKey(structuredClone(items[index] ?? {}));\n commit([...items.slice(0, index + 1), copy, ...items.slice(index + 1)]);\n },\n remove: (index: number) => commit(items.filter((_, at) => at !== index)),\n };\n};\n","import type { ComponentDefinition } from '@shapio/schema';\nimport { Trash2 } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { AddItemButton } from '../AddItemButton';\nimport { CanvasItemList } from '../CanvasItemList';\nimport { ComponentItemFields } from '../ComponentItemFields';\nimport { EmptyListRow } from '../EmptyListRow';\nimport { useFieldsEnvironment } from '../form/context';\nimport { newComponentItem } from '../helpers/formValues';\nimport { pointerOf } from '../helpers/issues';\nimport { hasRoomFor } from '../helpers/listLimits';\nimport { summarizeItem } from '../helpers/summary';\nimport { isRecord, type ItemValues } from '../helpers/values';\nimport { useCollapsedItems } from '../hooks/useCollapsedItems';\nimport { useFocusNewItem } from '../hooks/useFocusNewItem';\nimport { useItemIssueCount } from '../hooks/useItemIssueCount';\nimport { useListEditor } from '../hooks/useListEditor';\nimport { ItemCard } from '../ItemCard';\nimport type { BuiltInEditorProps } from '../types';\n\ntype RepeatableItemProps = {\n component: ComponentDefinition;\n item: ItemValues;\n itemKey: string;\n index: number;\n count: number;\n path: string;\n domId: string;\n collapsed: boolean;\n editable: boolean;\n list: ReturnType<typeof useListEditor>;\n onToggle: (key: string) => void;\n};\n\nconst RepeatableItem = ({\n component,\n item,\n itemKey,\n index,\n count,\n path,\n domId,\n collapsed,\n editable,\n list,\n onToggle,\n}: RepeatableItemProps) => {\n const itemPath = pointerOf(path, index);\n const issueCount = useItemIssueCount(itemPath);\n const onItemChange = useCallback((next: ItemValues) => list.update(index, next), [list, index]);\n return (\n <ItemCard\n id={domId}\n title={component.label}\n summary={summarizeItem(component, item)}\n index={index}\n count={count}\n collapsed={collapsed}\n issueCount={issueCount}\n editable={editable}\n onToggle={() => onToggle(itemKey)}\n onMove={(to) => list.move(index, to)}\n onDuplicate={() => list.duplicate(index)}\n onRemove={() => list.remove(index)}\n >\n <ComponentItemFields component={component} item={item} onItemChange={onItemChange} path={itemPath} />\n </ItemCard>\n );\n};\n\n/**\n * The repeatable list as blocks of the entry canvas, with \"Add …\" at its end while it has room. Empty, it\n * says so in a row with the same button (and the minimum, when one item would not be enough), so the field\n * never collapses to a bare heading.\n */\nconst CanvasRepeatable = (props: BuiltInEditorProps & { component: ComponentDefinition }) => {\n const { t } = useTranslation();\n const { component, value, onChange, path, labelId, inputId, readOnly, disabled, definition, field } = props;\n const list = useListEditor(value, onChange);\n const settings = definition.type === 'component' ? definition.settings : undefined;\n const editable = !readOnly && !disabled;\n const room = hasRoomFor(list.items.length, settings?.max);\n const add = (variant: 'outline' | 'ghost') =>\n editable && room ? (\n <AddItemButton\n label={t('content.items.add', { item: component.label })}\n variant={variant}\n onClick={() => list.add(newComponentItem(component, false))}\n />\n ) : null;\n const empty = list.items.length === 0;\n // The list stays mounted while empty, so the first item added gets focus like any other.\n return (\n <div className=\"space-y-1\">\n {empty ? <EmptyListRow min={settings?.min} action={add('outline')} /> : null}\n <CanvasItemList\n list={list}\n labelId={labelId}\n inputId={inputId}\n path={path}\n editable={editable}\n insertable={room ? [component] : []}\n componentOf={() => component}\n newItem={(next) => newComponentItem(next, false)}\n startCollapsed={field.options.collapsed === true}\n />\n {empty ? null : add('ghost')}\n </div>\n );\n};\n\nconst Repeatable = (props: BuiltInEditorProps & { component: ComponentDefinition }) => {\n const { t } = useTranslation();\n const { component, value, onChange, path, labelId, inputId, readOnly, disabled, definition } = props;\n const list = useListEditor(value, onChange);\n const { collapsed, toggle } = useCollapsedItems(list.keys, props.field.options.collapsed === true);\n const domId = useCallback((key: string) => `${inputId}-item-${key}`, [inputId]);\n useFocusNewItem(list.keys, domId);\n const max = definition.type === 'component' ? definition.settings.max : undefined;\n const editable = !readOnly && !disabled;\n return (\n <div className=\"space-y-3\">\n {list.items.length > 0 ? (\n <ol aria-labelledby={labelId} className=\"space-y-2\">\n {list.items.map((item, index) => {\n const key = list.keys[index] ?? String(index);\n return (\n <RepeatableItem\n key={key}\n component={component}\n item={item}\n itemKey={key}\n index={index}\n count={list.items.length}\n path={path}\n domId={domId(key)}\n collapsed={collapsed.has(key)}\n editable={editable}\n list={list}\n onToggle={toggle}\n />\n );\n })}\n </ol>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.items.empty')}</p>\n )}\n {editable && hasRoomFor(list.items.length, max) ? (\n <AddItemButton\n label={t('content.items.add', { item: component.label })}\n onClick={() => list.add(newComponentItem(component, false))}\n />\n ) : null}\n </div>\n );\n};\n\nconst Single = (props: BuiltInEditorProps & { component: ComponentDefinition }) => {\n const { t } = useTranslation();\n const { component, value, onChange, path, readOnly, disabled, field } = props;\n const editable = !readOnly && !disabled;\n const onItemChange = useCallback((next: ItemValues) => onChange(next), [onChange]);\n if (!isRecord(value)) {\n return editable ? (\n <AddItemButton\n label={t('content.items.add', { item: component.label })}\n onClick={() => onChange(newComponentItem(component, false))}\n />\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.items.empty')}</p>\n );\n }\n return (\n <div className=\"space-y-4 rounded-xl border bg-card p-5\">\n <ComponentItemFields component={component} item={value} onItemChange={onItemChange} path={path} />\n {editable && !field.required ? (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => onChange(null)}>\n <Trash2 aria-hidden=\"true\" />\n {t('content.items.removeSingle', { item: component.label })}\n </Button>\n ) : null}\n </div>\n );\n};\n\n/** `componentEditor`: a reusable group of fields, once or as a repeatable list. */\nexport const ComponentField = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { components } = useFieldsEnvironment();\n const { definition } = props;\n const component =\n definition.type === 'component' ? components.get(definition.settings.component) : undefined;\n if (!component || definition.type !== 'component') {\n return <p className=\"text-sm text-destructive\">{t('content.items.componentMissing')}</p>;\n }\n if (definition.settings.repeatable && props.appearance === 'canvas') {\n return <CanvasRepeatable {...props} component={component} />;\n }\n return definition.settings.repeatable ? (\n <Repeatable {...props} component={component} />\n ) : (\n <Single {...props} component={component} />\n );\n};\n","import { X } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\n\ntype ClearButtonProps = { label: string; onClear: () => void; disabled?: boolean };\n\n/** Empties a field whose control has no empty state of its own (select, radio, date). */\nexport const ClearButton = ({ label, onClear, disabled }: ClearButtonProps) => {\n const { t } = useTranslation();\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n disabled={disabled}\n aria-label={t('content.fields.clearValue', { field: label })}\n onClick={onClear}\n >\n <X aria-hidden=\"true\" />\n </Button>\n );\n};\n","import { Input } from '@/components/ui/input';\nimport { ClearButton } from '../ClearButton';\nimport { inputAria, textValue } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `datePicker`: a calendar date stored as `YYYY-MM-DD`. */\nexport const DateInput = (props: BuiltInEditorProps) => {\n const { value, onChange, onBlur, readOnly, disabled, definition, field } = props;\n const settings = definition.type === 'date' ? definition.settings : {};\n const text = textValue(value);\n return (\n <div className=\"flex items-center gap-1\">\n <Input\n {...inputAria(props)}\n type=\"date\"\n value={text}\n min={settings.min}\n max={settings.max}\n readOnly={readOnly}\n disabled={disabled}\n className=\"w-auto\"\n onChange={(event) => onChange(event.target.value === '' ? null : event.target.value)}\n onBlur={onBlur}\n />\n {text && !readOnly ? (\n <ClearButton label={field.label} disabled={disabled} onClear={() => onChange(null)} />\n ) : null}\n </div>\n );\n};\n","/**\n * `datetime` values are canonical UTC ISO-8601 text (`2026-10-01T08:00:00.000Z`, ADR 0001). The browser's\n * `datetime-local` input works in wall-clock time without a zone, so values are converted both ways, in the\n * viewer's time zone (default) or in UTC (`display: 'utc'`).\n */\nconst pad = (value: number, length = 2) => String(value).padStart(length, '0');\n\nexport const toDateTimeInput = (iso: unknown, utc: boolean): string => {\n if (typeof iso !== 'string') {\n return '';\n }\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n const parts = utc\n ? [\n date.getUTCFullYear(),\n date.getUTCMonth() + 1,\n date.getUTCDate(),\n date.getUTCHours(),\n date.getUTCMinutes(),\n date.getUTCSeconds(),\n ]\n : [\n date.getFullYear(),\n date.getMonth() + 1,\n date.getDate(),\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n ];\n const [year = 0, month = 1, day = 1, hours = 0, minutes = 0, seconds = 0] = parts;\n return `${pad(year, 4)}-${pad(month)}-${pad(day)}T${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;\n};\n\n/** `2026-10-01T10:00` or `…T10:00:30` → canonical UTC text; null for empty or unreadable input. */\nexport const fromDateTimeInput = (text: string, utc: boolean): string | null => {\n if (text === '') {\n return null;\n }\n const withSeconds = /T\\d{2}:\\d{2}$/.test(text) ? `${text}:00` : text;\n const date = new Date(utc ? `${withSeconds}Z` : withSeconds);\n return Number.isNaN(date.getTime()) ? null : date.toISOString();\n};\n\n/** The viewer's IANA time zone, for the hint under local-time inputs. */\nexport const localTimeZone = (): string => Intl.DateTimeFormat().resolvedOptions().timeZone;\n","import { useTranslation } from 'react-i18next';\nimport { Input } from '@/components/ui/input';\nimport { ClearButton } from '../ClearButton';\nimport { fromDateTimeInput, localTimeZone, toDateTimeInput } from '../helpers/dates';\nimport { inputAria, stringOption } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `dateTimePicker`: a moment in time, edited in local time (or UTC) and stored as canonical UTC text. */\nexport const DateTimeInput = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { inputId, value, onChange, onBlur, readOnly, disabled, field } = props;\n const utc = stringOption(props, 'display') === 'utc';\n const hintId = `${inputId}-zone`;\n return (\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-1\">\n <Input\n {...inputAria(props, hintId)}\n type=\"datetime-local\"\n step={1}\n value={toDateTimeInput(value, utc)}\n readOnly={readOnly}\n disabled={disabled}\n className=\"w-auto\"\n onChange={(event) => onChange(fromDateTimeInput(event.target.value, utc))}\n onBlur={onBlur}\n />\n {value && !readOnly ? (\n <ClearButton label={field.label} disabled={disabled} onClear={() => onChange(null)} />\n ) : null}\n </div>\n <p id={hintId} className=\"text-meta text-muted-foreground\">\n {utc\n ? t('content.fields.dateTime.utc')\n : t('content.fields.dateTime.local', { zone: localTimeZone() })}\n </p>\n </div>\n );\n};\n","import type { ComponentDefinition, FieldDefinition } from '@shapio/schema';\nimport { useFieldsEnvironment } from '../form/context';\n\n/** Components that can be stored in a field: a zone's allowed ones, a component field's own (else none). */\nexport const allowedComponentsOf = (\n definition: FieldDefinition,\n components: ReadonlyMap<string, ComponentDefinition>,\n): ComponentDefinition[] => {\n const ids =\n definition.type === 'dynamiczone'\n ? definition.settings.components\n : definition.type === 'component'\n ? [definition.settings.component]\n : [];\n return ids\n .map((id) => components.get(id))\n .filter((component): component is ComponentDefinition => component !== undefined);\n};\n\nexport const useAllowedComponents = (definition: FieldDefinition) =>\n allowedComponentsOf(definition, useFieldsEnvironment().components);\n","import type { ComponentDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { AddItemButton } from '../../AddItemButton';\nimport { useDeferredMenuAction } from '../../hooks/useDeferredMenuAction';\n\ntype AddSectionMenuProps = {\n allowed: readonly ComponentDefinition[];\n onAdd: (component: ComponentDefinition) => void;\n};\n\n/** \"Add section\": a menu of the zone's allowed components. Adds after the menu closes, so focus can move. */\nexport const AddSectionMenu = ({ allowed, onAdd }: AddSectionMenuProps) => {\n const { t } = useTranslation();\n const menu = useDeferredMenuAction();\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <AddItemButton label={t('content.items.addSection')} />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" onCloseAutoFocus={menu.onCloseAutoFocus}>\n {allowed.map((component) => (\n <DropdownMenuItem key={component.id} onSelect={() => menu.defer(() => onAdd(component))}>\n {component.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n};\n","import type { ComponentDefinition } from '@shapio/schema';\nimport { ChevronsDownUp, ChevronsUpDown } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { CanvasItemList } from '../CanvasItemList';\nimport { ComponentItemFields } from '../ComponentItemFields';\nimport { EmptyListRow } from '../EmptyListRow';\nimport { newComponentItem } from '../helpers/formValues';\nimport { pointerOf } from '../helpers/issues';\nimport { hasRoomFor } from '../helpers/listLimits';\nimport { summarizeItem } from '../helpers/summary';\nimport { COMPONENT_KEY, type ItemValues } from '../helpers/values';\nimport { useAllowedComponents } from '../hooks/useAllowedComponents';\nimport { useCollapsedItems } from '../hooks/useCollapsedItems';\nimport { useFocusNewItem } from '../hooks/useFocusNewItem';\nimport { useItemIssueCount } from '../hooks/useItemIssueCount';\nimport { useListEditor } from '../hooks/useListEditor';\nimport { ItemCard } from '../ItemCard';\nimport type { BuiltInEditorProps } from '../types';\nimport { AddSectionMenu } from './AddSectionMenu';\n\ntype ZoneItemProps = {\n allowed: readonly ComponentDefinition[];\n item: ItemValues;\n itemKey: string;\n index: number;\n count: number;\n path: string;\n domId: string;\n collapsed: boolean;\n editable: boolean;\n list: ReturnType<typeof useListEditor>;\n onToggle: (key: string) => void;\n};\n\nconst ZoneItem = ({\n allowed,\n item,\n itemKey,\n index,\n count,\n path,\n domId,\n collapsed,\n editable,\n list,\n onToggle,\n}: ZoneItemProps) => {\n const { t } = useTranslation();\n const component = allowed.find((candidate) => candidate.apiKey === item[COMPONENT_KEY]);\n const itemPath = pointerOf(path, index);\n const issueCount = useItemIssueCount(itemPath);\n const onItemChange = useCallback((next: ItemValues) => list.update(index, next), [list, index]);\n return (\n <ItemCard\n id={domId}\n title={component?.label ?? t('content.items.unknownComponent', { key: String(item[COMPONENT_KEY]) })}\n summary={component ? summarizeItem(component, item) : ''}\n index={index}\n count={count}\n collapsed={collapsed}\n issueCount={issueCount}\n editable={editable}\n onToggle={() => onToggle(itemKey)}\n onMove={(to) => list.move(index, to)}\n onDuplicate={component ? () => list.duplicate(index) : undefined}\n onRemove={() => list.remove(index)}\n >\n {component ? (\n <ComponentItemFields component={component} item={item} onItemChange={onItemChange} path={itemPath} />\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.items.unknownComponentHint')}</p>\n )}\n </ItemCard>\n );\n};\n\n/**\n * The zone as blocks of the entry canvas. Empty, it says so in a row with \"Add section\" (and the minimum,\n * when one section would not be enough); the list stays mounted so the first section added gets focus.\n */\nconst CanvasZone = (props: BuiltInEditorProps) => {\n const { value, onChange, path, labelId, inputId, readOnly, disabled, definition, field } = props;\n const list = useListEditor(value, onChange);\n const allowed = useAllowedComponents(definition);\n const settings = definition.type === 'dynamiczone' ? definition.settings : undefined;\n const editable = !readOnly && !disabled;\n const room = hasRoomFor(list.items.length, settings?.max);\n return (\n <div>\n {list.items.length === 0 ? (\n <EmptyListRow\n min={settings?.min}\n action={\n editable && room && allowed.length > 0 ? (\n <AddSectionMenu\n allowed={allowed}\n onAdd={(component) => list.add(newComponentItem(component, true))}\n />\n ) : null\n }\n />\n ) : null}\n <CanvasItemList\n list={list}\n labelId={labelId}\n inputId={inputId}\n path={path}\n editable={editable}\n insertable={room ? allowed : []}\n componentOf={(item) => allowed.find((candidate) => candidate.apiKey === item[COMPONENT_KEY])}\n newItem={(component) => newComponentItem(component, true)}\n startCollapsed={field.options.collapsed === true}\n />\n </div>\n );\n};\n\n/**\n * `dynamicZoneEditor`: an ordered list of sections, each one of the zone's allowed components. Sections can\n * be added by type, reordered (buttons or Alt+↑/↓), duplicated, collapsed (with a readable summary) and\n * removed.\n */\nexport const DynamicZoneField = (props: BuiltInEditorProps) =>\n props.appearance === 'canvas' ? <CanvasZone {...props} /> : <FormZone {...props} />;\n\nconst FormZone = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { value, onChange, path, labelId, inputId, readOnly, disabled, definition, field } = props;\n const list = useListEditor(value, onChange);\n const { collapsed, toggle, setAll } = useCollapsedItems(list.keys, field.options.collapsed === true);\n const domId = useCallback((key: string) => `${inputId}-item-${key}`, [inputId]);\n useFocusNewItem(list.keys, domId);\n const allowed = useAllowedComponents(definition);\n const max = definition.type === 'dynamiczone' ? definition.settings.max : undefined;\n const editable = !readOnly && !disabled;\n const allCollapsed = list.keys.length > 0 && list.keys.every((key) => collapsed.has(key));\n return (\n <div className=\"space-y-3\">\n {list.items.length > 1 ? (\n <div className=\"flex justify-end\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => setAll(list.keys, !allCollapsed)}>\n {allCollapsed ? <ChevronsUpDown aria-hidden=\"true\" /> : <ChevronsDownUp aria-hidden=\"true\" />}\n {allCollapsed ? t('content.items.expandAll') : t('content.items.collapseAll')}\n </Button>\n </div>\n ) : null}\n {list.items.length > 0 ? (\n <ol aria-labelledby={labelId} className=\"space-y-2\">\n {list.items.map((item, index) => {\n const key = list.keys[index] ?? String(index);\n return (\n <ZoneItem\n key={key}\n allowed={allowed}\n item={item}\n itemKey={key}\n index={index}\n count={list.items.length}\n path={path}\n domId={domId(key)}\n collapsed={collapsed.has(key)}\n editable={editable}\n list={list}\n onToggle={toggle}\n />\n );\n })}\n </ol>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.items.emptyZone')}</p>\n )}\n {editable && hasRoomFor(list.items.length, max) ? (\n <AddSectionMenu\n allowed={allowed}\n onAdd={(component) => list.add(newComponentItem(component, true))}\n />\n ) : null}\n </div>\n );\n};\n","type ParseErrorProps = { id: string; message: string | undefined };\n\n/** An editor's own \"this text can't be read\" message (the value is not sent until it parses). */\nexport const ParseError = ({ id, message }: ParseErrorProps) =>\n message ? (\n <p id={id} role=\"alert\" className=\"text-sm text-destructive\">\n {message}\n </p>\n ) : null;\n","import { Braces } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Textarea } from '@/components/ui/textarea';\nimport { inputAria, numberOption } from '../helpers/props';\nimport { isDeepEqual } from '../helpers/values';\nimport { ParseError } from '../ParseError';\nimport type { BuiltInEditorProps } from '../types';\n\nconst DEFAULT_ROWS = 8;\nconst INDENT = 2;\n\nconst format = (value: unknown) =>\n value === null || value === undefined ? '' : JSON.stringify(value, null, INDENT);\n\nconst parse = (text: string): { ok: true; value: unknown } | { ok: false; message: string } => {\n if (text.trim() === '') {\n return { ok: true, value: null };\n }\n try {\n return { ok: true, value: JSON.parse(text) as unknown };\n } catch (error) {\n return { ok: false, message: error instanceof Error ? error.message : String(error) };\n }\n};\n\n/** `jsonEditor`: any JSON value, as text. Only text that parses becomes the value; errors show inline. */\nexport const JsonEditor = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { inputId, value, onChange, onBlur, readOnly, disabled } = props;\n const [text, setText] = useState(() => format(value));\n const [problem, setProblem] = useState<string | undefined>();\n const [seen, setSeen] = useState(value);\n // Follow outside changes (reload, restore, copy from another locale) unless they match what's typed.\n if (!Object.is(seen, value)) {\n setSeen(value);\n const parsed = parse(text);\n if (!parsed.ok || !isDeepEqual(parsed.value, value ?? null)) {\n setText(format(value));\n setProblem(undefined);\n }\n }\n const errorId = `${inputId}-parse`;\n return (\n <div className=\"space-y-1\">\n <Textarea\n {...inputAria(props, problem ? errorId : undefined)}\n aria-invalid={props.validation.invalid || problem !== undefined || undefined}\n rows={numberOption(props, 'rows') ?? DEFAULT_ROWS}\n value={text}\n spellCheck={false}\n readOnly={readOnly}\n disabled={disabled}\n className=\"font-mono text-sm\"\n onChange={(event) => {\n setText(event.target.value);\n const parsed = parse(event.target.value);\n setProblem(parsed.ok ? undefined : parsed.message);\n if (parsed.ok) {\n onChange(parsed.value);\n }\n }}\n onBlur={onBlur}\n />\n <div className=\"flex items-start justify-between gap-2\">\n <ParseError\n id={errorId}\n message={problem ? t('content.fields.json.invalid', { reason: problem }) : undefined}\n />\n {!readOnly ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n disabled={disabled || problem !== undefined || text.trim() === ''}\n onClick={() => setText(format(value))}\n >\n <Braces aria-hidden=\"true\" />\n {t('content.fields.json.format')}\n </Button>\n ) : null}\n </div>\n </div>\n );\n};\n","import { ArrowLeft, ArrowRight, ImageOff, Trash2 } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useMediaAsset } from '@/api/media';\nimport { Button } from '@/components/ui/button';\nimport { Skeleton } from '@/components/ui/skeleton';\nimport { Thumbnail } from '@/features/Media/Thumbnail';\n\ntype GalleryTileProps = {\n assetId: string;\n index: number;\n count: number;\n editable: boolean;\n onMove: (to: number) => void;\n onRemove: () => void;\n};\n\n/** One file of a canvas gallery: its thumbnail and name, with move and remove on hover or focus. */\nexport const GalleryTile = ({ assetId, index, count, editable, onMove, onRemove }: GalleryTileProps) => {\n const { t } = useTranslation();\n const asset = useMediaAsset(assetId);\n const name = asset.data?.filename ?? assetId;\n return (\n <li className=\"group/tile relative space-y-1.5\">\n {asset.data ? (\n <Thumbnail asset={asset.data} className=\"aspect-square w-full rounded-xl\" />\n ) : asset.isPending ? (\n <Skeleton className=\"aspect-square w-full rounded-xl\" />\n ) : (\n <div className=\"flex aspect-square w-full items-center justify-center rounded-xl bg-muted text-muted-foreground\">\n <ImageOff aria-hidden=\"true\" className=\"size-5\" />\n </div>\n )}\n <p className=\"truncate text-meta text-muted-foreground\">\n {asset.isError ? t('content.media.missing') : name}\n </p>\n {editable ? (\n <div className=\"absolute top-2 right-2 flex gap-1 rounded-lg bg-popover p-0.5 opacity-0 shadow-sm transition-opacity group-focus-within/tile:opacity-100 group-hover/tile:opacity-100\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={t('content.items.moveUp', { item: name, position: index + 1 })}\n disabled={index === 0}\n onClick={() => onMove(index - 1)}\n >\n <ArrowLeft aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={t('content.items.moveDown', { item: name, position: index + 1 })}\n disabled={index === count - 1}\n onClick={() => onMove(index + 1)}\n >\n <ArrowRight aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={t('content.media.remove', { name })}\n onClick={onRemove}\n >\n <Trash2 aria-hidden=\"true\" />\n </Button>\n </div>\n ) : null}\n </li>\n );\n};\n","import { ImagePlus } from 'lucide-react';\nimport { useState, type DragEvent } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { cn } from '@/helpers/cn';\nimport { logError } from '@/helpers/reportError';\nimport { useFieldsEnvironment } from '../../form/context';\nimport { moveItem } from '../../helpers/values';\nimport { GalleryTile } from '../GalleryTile';\n\ntype GalleryProps = {\n ids: readonly string[];\n labelId: string;\n inputId: string;\n editable: boolean;\n /** More files fit (under the field's `max`). */\n canAdd: boolean;\n onPick: () => void;\n commit: (ids: string[]) => void;\n};\n\n/**\n * Several files as a gallery block of the canvas: thumbnails in a grid, a tile to add more from the\n * library, and files dropped onto it uploaded straight in (with `media.write`).\n */\nexport const Gallery = ({ ids, labelId, inputId, editable, canAdd, onPick, commit }: GalleryProps) => {\n const { t } = useTranslation();\n const { uploadMedia } = useFieldsEnvironment();\n const [dropping, setDropping] = useState(false);\n const [uploading, setUploading] = useState(0);\n const acceptsFiles = editable && canAdd && uploadMedia !== undefined;\n const onDrop = async (event: DragEvent) => {\n setDropping(false);\n const files = [...event.dataTransfer.files];\n if (!acceptsFiles || files.length === 0 || !uploadMedia) {\n return;\n }\n event.preventDefault();\n setUploading((count) => count + files.length);\n const added: string[] = [];\n for (const file of files) {\n try {\n added.push((await uploadMedia(file)).id);\n } catch (error) {\n logError(error, `uploading ${file.name} into a gallery`);\n toast.error(t('entry.upload.failed', { name: file.name }));\n } finally {\n setUploading((count) => count - 1);\n }\n }\n if (added.length > 0) {\n commit([...ids, ...added]);\n }\n };\n return (\n <div\n className={cn('rounded-xl font-sans', dropping && 'ring-[3px] ring-ring/50')}\n onDragOver={(event) => {\n if (acceptsFiles && event.dataTransfer.types.includes('Files')) {\n event.preventDefault();\n setDropping(true);\n }\n }}\n onDragLeave={() => setDropping(false)}\n onDrop={(event) => void onDrop(event)}\n >\n <ul aria-labelledby={labelId} className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n {ids.map((id, index) => (\n <GalleryTile\n key={id}\n assetId={id}\n index={index}\n count={ids.length}\n editable={editable}\n onMove={(to) => commit(moveItem(ids, index, to))}\n onRemove={() => commit(ids.filter((item) => item !== id))}\n />\n ))}\n </ul>\n {editable && canAdd ? (\n <button\n id={inputId}\n type=\"button\"\n onClick={onPick}\n className={cn(\n 'mt-3 flex h-20 w-full items-center justify-center gap-2 rounded-xl border border-dashed text-sm text-muted-foreground outline-none hover:bg-muted/50 hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50',\n )}\n >\n <ImagePlus aria-hidden=\"true\" className=\"size-4\" />\n {uploading > 0\n ? t('entry.upload.uploadingCount', { count: uploading })\n : uploadMedia\n ? t('entry.gallery.addOrDrop')\n : t('content.media.add')}\n </button>\n ) : null}\n </div>\n );\n};\n","import { ImagePlus } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { reportError } from '@/helpers/reportError';\nimport { useMediaPermissions } from '@/hooks/useMediaPermissions';\nimport { moveItem, toList } from '../helpers/values';\nimport type { BuiltInEditorProps } from '../types';\nimport { AssetTile } from './AssetTile';\nimport { Gallery } from './Gallery';\n\n/**\n * `mediaPicker`: one or several files from the media library (chosen in a sheet, uploads included).\n * The value is asset IDs; previews, alt text and variants come from the library.\n */\nexport const MediaField = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { canWrite } = useMediaPermissions();\n const { value, onChange, onBlur, readOnly, disabled, definition, context, inputId, labelId, describedBy } =\n props;\n const settings = definition.type === 'media' ? definition.settings : { multiple: false };\n const multiple = settings.multiple;\n const ids = toList<string>(value).filter((id): id is string => typeof id === 'string');\n const editable = !readOnly && !disabled;\n const commit = (next: string[]) => {\n onChange(multiple ? (next.length > 0 ? next : null) : (next[0] ?? null));\n onBlur();\n };\n const pick = async () => {\n try {\n const picked = await context.pickMedia({\n multiple,\n ...('allowedKinds' in settings && settings.allowedKinds\n ? { allowedKinds: settings.allowedKinds }\n : {}),\n });\n if (picked && picked.length > 0) {\n const chosen = picked.map((asset) => asset.id);\n commit(multiple ? [...ids, ...chosen.filter((id) => !ids.includes(id))] : chosen.slice(0, 1));\n }\n } catch (error) {\n reportError(error, 'picking media');\n }\n };\n const max = 'max' in settings ? settings.max : undefined;\n if (multiple && props.appearance === 'canvas') {\n return (\n <Gallery\n ids={ids}\n labelId={labelId}\n inputId={inputId}\n editable={editable}\n canAdd={max === undefined || ids.length < max}\n onPick={() => void pick()}\n commit={commit}\n />\n );\n }\n return (\n <div role=\"group\" aria-labelledby={labelId} aria-describedby={describedBy} className=\"space-y-2\">\n {ids.length > 0 ? (\n <ul className=\"space-y-2\">\n {ids.map((id, index) => (\n <AssetTile\n key={id}\n assetId={id}\n inputId={inputId}\n index={index}\n count={ids.length}\n editable={editable}\n canEditAlt={canWrite && !readOnly}\n onMove={multiple ? (to) => commit(moveItem(ids, index, to)) : undefined}\n onRemove={() => commit(ids.filter((item) => item !== id))}\n />\n ))}\n </ul>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.media.empty')}</p>\n )}\n {editable && (multiple ? max === undefined || ids.length < max : true) ? (\n <Button id={inputId} type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void pick()}>\n <ImagePlus aria-hidden=\"true\" />\n {multiple\n ? t('content.media.add')\n : ids.length > 0\n ? t('content.media.replace')\n : t('content.media.chooseOne')}\n </Button>\n ) : null}\n </div>\n );\n};\n","import { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Input } from '@/components/ui/input';\nimport { inputAria, numberOption, stringOption, textValue } from '../helpers/props';\nimport { ParseError } from '../ParseError';\nimport type { BuiltInEditorProps } from '../types';\n\nconst INTEGER = /^-?\\d+$/;\nconst NUMBER = /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][-+]?\\d+)?$/;\n\n/** Text → value: numbers for `number`/`integer`, canonical strings for `decimal`/`biginteger`. */\nconst parse = (type: string, text: string): { ok: true; value: number | string | null } | { ok: false } => {\n const trimmed = text.trim();\n if (trimmed === '') {\n return { ok: true, value: null };\n }\n if (type === 'decimal' || type === 'biginteger') {\n // Kept as typed: the format check (and the server) report anything that is not a canonical number.\n return { ok: true, value: trimmed };\n }\n if (!(type === 'integer' ? INTEGER : NUMBER).test(trimmed)) {\n return { ok: false };\n }\n const number = Number(trimmed);\n return Number.isFinite(number) && (type !== 'integer' || Number.isSafeInteger(number))\n ? { ok: true, value: number }\n : { ok: false };\n};\n\n/**\n * `numberInput`: number, integer, decimal and big integer. Typed as text so partial input (\"1.\", \"-\")\n * isn't lost; only text that parses is reported as the value.\n */\nexport const NumberInput = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { inputId, value, onChange, onBlur, readOnly, disabled, definition } = props;\n const [text, setText] = useState(() => textValue(value));\n const [invalid, setInvalid] = useState(false);\n const [seen, setSeen] = useState(value);\n // Follow outside changes (reload, restore, copy from another locale) unless they match what's typed.\n if (!Object.is(seen, value)) {\n setSeen(value);\n const parsed = parse(definition.type, text);\n if (!parsed.ok || parsed.value !== value) {\n setText(textValue(value));\n setInvalid(false);\n }\n }\n const parseErrorId = `${inputId}-parse`;\n const integer = definition.type === 'integer' || definition.type === 'biginteger';\n return (\n <div className=\"space-y-1\">\n <Input\n {...inputAria(props, invalid ? parseErrorId : undefined)}\n aria-invalid={props.validation.invalid || invalid || undefined}\n inputMode={integer ? 'numeric' : 'decimal'}\n value={text}\n placeholder={stringOption(props, 'placeholder')}\n step={numberOption(props, 'step')}\n readOnly={readOnly}\n disabled={disabled}\n className=\"tabular-nums\"\n onChange={(event) => {\n setText(event.target.value);\n const parsed = parse(definition.type, event.target.value);\n setInvalid(!parsed.ok);\n if (parsed.ok) {\n onChange(parsed.value);\n }\n }}\n onBlur={onBlur}\n />\n <ParseError\n id={parseErrorId}\n message={\n invalid\n ? t(integer ? 'content.fields.number.notInteger' : 'content.fields.number.notNumber')\n : undefined\n }\n />\n </div>\n );\n};\n","import { Label } from '@/components/ui/label';\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';\nimport { cn } from '@/helpers/cn';\nimport { ClearButton } from '../ClearButton';\nimport { choicesOf, fromChoice, toChoice } from '../helpers/choices';\nimport { stringOption } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `radio`: radio buttons for a single-choice enum, vertical or horizontal. */\nexport const RadioInput = (props: BuiltInEditorProps) => {\n const { inputId, labelId, describedBy, value, onChange, onBlur, readOnly, disabled, field, validation } =\n props;\n const current = toChoice(value);\n const horizontal = stringOption(props, 'layout') === 'horizontal';\n return (\n <div className=\"flex items-start gap-2\">\n <RadioGroup\n aria-labelledby={labelId}\n aria-describedby={describedBy}\n aria-invalid={validation.invalid || undefined}\n value={current}\n disabled={disabled || readOnly}\n onValueChange={(choice) => onChange(fromChoice(props, choice))}\n onBlur={onBlur}\n className={cn(horizontal && 'flex flex-wrap gap-x-6')}\n >\n {choicesOf(props).map((choice) => (\n <div key={choice.value} className=\"flex items-center gap-2\">\n <RadioGroupItem id={`${inputId}-${choice.value}`} value={choice.value} />\n <Label htmlFor={`${inputId}-${choice.value}`} className=\"font-normal\">\n {choice.label}\n </Label>\n </div>\n ))}\n </RadioGroup>\n {current && !field.required && !readOnly ? (\n <ClearButton label={field.label} disabled={disabled} onClear={() => onChange(null)} />\n ) : null}\n </div>\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useMemo } from 'react';\nimport { useEntryList } from '@/api/content';\nimport { titleFieldOf } from '../helpers/titles';\n\nconst MAX_LOOKUP = 100;\n\n/** Titles of related entries by ID, read in one list request (`filters[id][$in]`). */\nexport const useEntryLabels = (\n model: ModelDefinition | undefined,\n ids: readonly string[],\n locale: string | null,\n) => {\n const title = model ? titleFieldOf(model) : undefined;\n const lookup = ids.slice(0, MAX_LOOKUP);\n const query = {\n filters: { id: { $in: [...lookup].sort() } },\n pageSize: Math.max(lookup.length, 1),\n ...(title ? { fields: [title.apiKey] } : {}),\n ...(locale && model?.localized ? { locale } : {}),\n };\n const list = useEntryList(model?.apiKey ?? '', query, model !== undefined && lookup.length > 0);\n const items = list.data?.items;\n const byId = useMemo(() => new Map((items ?? []).map((item) => [item.id, item])), [items]);\n return { byId, isLoading: list.isPending && lookup.length > 0, error: list.error };\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport { memo } from 'react';\nimport { FieldControl, type FieldLayout } from '../../FieldControl';\nimport { useTopLevelValue } from '../../hooks/useTopLevelValue';\nimport { useFieldsEnvironment } from '../context';\n\ntype TopLevelFieldProps = {\n field: FieldDefinition;\n layout?: FieldLayout;\n className?: string;\n};\n\n/** A field of the entry itself, as a labelled control: subscribes to its own value only. */\nexport const TopLevelField = memo(({ field, layout, className }: TopLevelFieldProps) => {\n const { model } = useFieldsEnvironment();\n const { value, onChange } = useTopLevelValue(field);\n return (\n <FieldControl\n field={field}\n owner={model}\n value={value}\n onChange={onChange}\n path={`/${field.apiKey}`}\n topLevel\n layout={layout}\n className={className}\n />\n );\n});\n\nTopLevelField.displayName = 'TopLevelField';\n","import type { FieldDefinition } from '@shapio/schema';\nimport { FieldGrid } from '../../FieldGrid';\nimport type { FieldGridMode } from '../../helpers/widthClasses';\nimport { EntrySiblings } from '../EntrySiblings';\nimport { TopLevelField } from '../TopLevelField';\n\ntype EntryFieldsProps = {\n fields: readonly FieldDefinition[];\n /** `widths` for a form-layout entry (each field at its `width`); quick edit keeps the compact split. */\n mode?: FieldGridMode;\n};\n\n/** The entry's own fields (one section of the form). */\nexport const EntryFields = ({ fields, mode }: EntryFieldsProps) => (\n <EntrySiblings>\n <FieldGrid\n fields={fields}\n mode={mode}\n renderField={(field, className) => (\n <TopLevelField key={field.id} field={field} layout=\"stacked\" className={className} />\n )}\n />\n </EntrySiblings>\n);\n","import type { ContentIssue } from '@shapio/client';\nimport { createStore } from 'zustand/vanilla';\nimport { dirtyKeysOf, mergeSaved } from '../helpers/formValues';\nimport type { FormValues } from '../helpers/values';\n\n/**\n * State of one entry form: the values being edited, the baseline they are compared with (what the server\n * last returned), and validation issues. One store per open form (the page's form and an inline-create\n * drawer each have their own), so fields subscribe to just their own value.\n */\nexport type EntryFormState = {\n values: FormValues;\n baseline: FormValues;\n /** Server issues from the last save, plus none of the client-side checks (computed per field). */\n issues: readonly ContentIssue[];\n /** Paths whose client-side checks are shown (after the field was left, or after a save attempt). */\n touched: ReadonlySet<string>;\n /** Show every field's client-side issues (set by a save or publish attempt). */\n revealAll: boolean;\n setValue: (apiKey: string, value: unknown) => void;\n /** Replaces several values at once (copy from another locale, reload keeping local edits). */\n patchValues: (values: FormValues) => void;\n touch: (path: string) => void;\n reveal: () => void;\n setIssues: (issues: readonly ContentIssue[]) => void;\n /** Starts over from values loaded from the server. */\n load: (values: FormValues) => void;\n /** Rebases onto newly loaded values, keeping these local changes on top. */\n rebase: (values: FormValues, local: FormValues) => void;\n /** Accepts a save's result; see `mergeSaved`. */\n acceptSaved: (sent: FormValues, saved: FormValues) => void;\n};\n\nexport type EntryFormStore = ReturnType<typeof createEntryFormStore>;\n\nconst withoutIssuesUnder = (issues: readonly ContentIssue[], apiKey: string) => {\n const prefix = `/${apiKey}`;\n return issues.filter((issue) => issue.path !== prefix && !issue.path.startsWith(`${prefix}/`));\n};\n\nexport const createEntryFormStore = (initial: FormValues) =>\n createStore<EntryFormState>()((set) => ({\n values: initial,\n baseline: initial,\n issues: [],\n touched: new Set(),\n revealAll: false,\n setValue: (apiKey, value) =>\n set((state) => ({\n values: { ...state.values, [apiKey]: value },\n // A changed value makes the server's verdict on it stale.\n issues: withoutIssuesUnder(state.issues, apiKey),\n })),\n patchValues: (values) =>\n set((state) => ({\n values: { ...state.values, ...values },\n issues: Object.keys(values).reduce(withoutIssuesUnder, state.issues),\n })),\n touch: (path) =>\n set((state) => (state.touched.has(path) ? state : { touched: new Set([...state.touched, path]) })),\n reveal: () => set({ revealAll: true }),\n setIssues: (issues) => set({ issues }),\n load: (values) => set({ values, baseline: values, issues: [], touched: new Set(), revealAll: false }),\n rebase: (values, local) => set({ values: { ...values, ...local }, baseline: values, issues: [] }),\n acceptSaved: (sent, saved) => set((state) => mergeSaved(state.values, sent, saved)),\n }));\n\n/** Top-level API keys with unsaved changes. */\nexport const selectDirtyKeys = (state: Pick<EntryFormState, 'values' | 'baseline'>) =>\n dirtyKeysOf(state.values, state.baseline);\n","import { ShapioApiError, type ContentIssue, type EntryReferrer } from '@shapio/client';\nimport { isRecord } from './values';\n\n/** The issues of a 422 CONTENT_INVALID answer (empty for any other error). */\nexport const contentIssuesOf = (error: unknown): ContentIssue[] => {\n if (!(error instanceof ShapioApiError) || error.code !== 'CONTENT_INVALID' || !isRecord(error.details)) {\n return [];\n }\n const issues = error.details.issues;\n return Array.isArray(issues)\n ? issues.filter(\n (issue): issue is ContentIssue =>\n isRecord(issue) && typeof issue.path === 'string' && typeof issue.code === 'string',\n )\n : [];\n};\n\n/** The entries still pointing at one being deleted (409 ENTRY_REFERENCED). */\nexport const referrersOf = (error: unknown): EntryReferrer[] => {\n if (!(error instanceof ShapioApiError) || error.code !== 'ENTRY_REFERENCED' || !isRecord(error.details)) {\n return [];\n }\n const referrers = error.details.referrers;\n return Array.isArray(referrers) ? referrers.filter((item): item is EntryReferrer => isRecord(item)) : [];\n};\n\n/** A save that lost a race: the draft moved (another session) or the model changed while saving. */\nexport const isEditConflict = (error: unknown): error is ShapioApiError =>\n error instanceof ShapioApiError &&\n error.status === 409 &&\n (error.code === 'CONTENT_VERSION_CONFLICT' || error.code === 'SCHEMA_CHANGED');\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useStore } from 'zustand';\nimport { useCreateEntry } from '@/api/content';\nimport { FormError } from '@/components/FormError';\nimport { SubmitButton } from '@/components/SubmitButton';\nimport { Button } from '@/components/ui/button';\nimport { Sheet, SheetBody, SheetContent, SheetFooter, SheetHeader, SheetTitle } from '@/components/ui/sheet';\nimport { useDiscardGuard } from '@/hooks/useDiscardGuard';\nimport { useFieldsEnvironment } from '../../form/context';\nimport { EntryFields } from '../../form/EntryFields';\nimport { FieldsProvider } from '../../form/FieldsProvider';\nimport { createEntryFormStore, selectDirtyKeys } from '../../form/store';\nimport { contentIssuesOf } from '../../helpers/apiErrors';\nimport { buildCreateData, defaultFormValues, liveFields } from '../../helpers/formValues';\nimport { fieldGridModeOf } from '../../helpers/widthClasses';\n\ntype InlineCreateSheetProps = {\n target: ModelDefinition;\n onClose: () => void;\n onCreated: (id: string) => void;\n};\n\n/**\n * Creates an entry of a relation's target model without leaving the form (the relation editor's\n * `allowInlineCreate` option). The server checks the create permission; a refusal shows here.\n */\nexport const InlineCreateSheet = ({ target, onClose, onCreated }: InlineCreateSheetProps) => {\n const { t } = useTranslation();\n const outer = useFieldsEnvironment();\n const [store] = useState(() => createEntryFormStore(defaultFormValues(target.fields)));\n const dirty = useStore(store, (state) => selectDirtyKeys(state).length > 0);\n const create = useCreateEntry(target.apiKey);\n const { requestOpenChange, discardPrompt } = useDiscardGuard({\n dirty,\n pending: create.isPending,\n onOpenChange: (open) => (open ? undefined : onClose()),\n });\n const locale = target.localized ? outer.locale : null;\n const environment = useMemo(\n () => ({\n ...outer,\n idPrefix: `${outer.idPrefix}inline-`,\n model: target,\n locale,\n entryId: null,\n readOnly: false,\n disabled: create.isPending,\n }),\n [outer, target, locale, create.isPending],\n );\n const submit = async () => {\n store.getState().reveal();\n try {\n const entry = await create.mutateAsync({\n ...(locale ? { locale } : {}),\n data: buildCreateData(store.getState().values),\n });\n onCreated(entry.id);\n } catch (error) {\n // Logged by the mutation cache; issues show on the fields, anything else above the buttons.\n store.getState().setIssues(contentIssuesOf(error));\n }\n };\n const issues = contentIssuesOf(create.error);\n return (\n <>\n <Sheet open onOpenChange={requestOpenChange}>\n <SheetContent size=\"md\" aria-describedby={undefined}>\n <SheetHeader>\n <SheetTitle>{t('content.relation.createTitle', { model: target.label })}</SheetTitle>\n </SheetHeader>\n <form\n noValidate\n className=\"flex min-h-0 flex-1 flex-col\"\n onSubmit={(event) => {\n event.preventDefault();\n void submit();\n }}\n >\n <SheetBody className=\"space-y-5\">\n <FieldsProvider environment={environment} store={store}>\n <EntryFields fields={liveFields(target.fields)} mode={fieldGridModeOf(target)} />\n </FieldsProvider>\n {create.isError && issues.length === 0 ? <FormError error={create.error} /> : null}\n {issues.length > 0 ? (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {t('content.form.fixProblems', { count: issues.length })}\n </p>\n ) : null}\n </SheetBody>\n <SheetFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => requestOpenChange(false)}>\n {t('common.cancel')}\n </Button>\n <SubmitButton pending={create.isPending} pendingLabel={t('content.form.creating')}>\n {t('content.relation.createAndLink')}\n </SubmitButton>\n </SheetFooter>\n </form>\n </SheetContent>\n </Sheet>\n {discardPrompt}\n </>\n );\n};\n","import { useSyncExternalStore } from 'react';\n\n// Tailwind's `md` breakpoint (48rem).\nconst MD_QUERY = '(min-width: 48rem)';\n\nconst subscribe = (onChange: () => void) => {\n const query = window.matchMedia(MD_QUERY);\n query.addEventListener('change', onChange);\n return () => query.removeEventListener('change', onChange);\n};\n\nconst getSnapshot = () => window.matchMedia(MD_QUERY).matches;\n\n/** True from the `md` breakpoint up: pickers anchor a popover to their field there, and use a bottom sheet below. */\nexport const useIsMdUp = () => useSyncExternalStore(subscribe, getSnapshot, () => true);\n","import { useState } from 'react';\n\n/**\n * The highlighted option of a listbox driven by `aria-activedescendant` (focus stays on the combobox).\n * Remembered by id, so it survives new results and clears itself when its option goes away.\n */\nexport const useActiveOption = (ids: readonly string[]) => {\n const [rememberedId, setActiveId] = useState<string | undefined>();\n const activeId = rememberedId !== undefined && ids.includes(rememberedId) ? rememberedId : undefined;\n /** ↓ from nothing goes to the first option, ↑ to the last; both stop at the ends. */\n const move = (delta: 1 | -1) => {\n if (ids.length === 0) {\n return;\n }\n const index = activeId === undefined ? -1 : ids.indexOf(activeId);\n const next = index === -1 ? (delta === 1 ? 0 : ids.length - 1) : index + delta;\n setActiveId(ids[Math.min(Math.max(next, 0), ids.length - 1)]);\n };\n return {\n activeId,\n setActiveId,\n move,\n first: () => setActiveId(ids[0]),\n last: () => setActiveId(ids.at(-1)),\n };\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { Check, Search } from 'lucide-react';\nimport { useEffect, useId, useState, type KeyboardEvent } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useEntryList } from '@/api/content';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { Input } from '@/components/ui/input';\nimport { cn } from '@/helpers/cn';\nimport { useDebouncedValue } from '@/hooks/useDebouncedValue';\nimport { isSearchable, labelOf } from '../../../helpers/titles';\nimport { useActiveOption } from '../hooks/useActiveOption';\n\nconst PAGE_SIZE = 20;\nconst SEARCH_DEBOUNCE_MS = 300;\n\ntype ResultsProps = {\n target: ModelDefinition;\n locale: string | null;\n multiple: boolean;\n /** Linked now: shown as selected. */\n selected: readonly string[];\n /** Never offered (the entry being edited, for self-relations). */\n exclude: readonly string[];\n /** No more may be linked (relation `max`): unselected options are disabled. */\n full: boolean;\n onPick: (id: string) => void;\n onUnpick: (id: string) => void;\n className?: string;\n /** Sizing of the scrolling result list (the popover caps it; the sheet lets it grow). */\n listClassName?: string;\n};\n\n/**\n * The relation picker's body: a combobox search over the target's titles (when it has a searchable title)\n * and the matching entries as a listbox. Focus stays in the search box; ↑/↓ move the highlighted option\n * (`aria-activedescendant`) and Enter picks it. Without a search box the listbox itself takes focus.\n */\nexport const Results = ({\n target,\n locale,\n multiple,\n selected,\n exclude,\n full,\n onPick,\n onUnpick,\n className,\n listClassName,\n}: ResultsProps) => {\n const { t } = useTranslation();\n const listboxId = useId();\n const [text, setText] = useState('');\n const q = useDebouncedValue(text.trim(), SEARCH_DEBOUNCE_MS);\n const searchable = isSearchable(target);\n const list = useEntryList(target.apiKey, {\n pageSize: PAGE_SIZE,\n ...(q && searchable ? { q } : {}),\n ...(locale && target.localized ? { locale } : {}),\n });\n const items = (list.data?.items ?? []).filter((item) => !exclude.includes(item.id));\n const active = useActiveOption(items.map((item) => item.id));\n const optionId = (id: string) => `${listboxId}-${id}`;\n const activeDescendant = active.activeId ? optionId(active.activeId) : undefined;\n\n useEffect(() => {\n if (activeDescendant) {\n document.getElementById(activeDescendant)?.scrollIntoView({ block: 'nearest' });\n }\n }, [activeDescendant]);\n\n const choose = (id: string) => {\n const isSelected = selected.includes(id);\n if (multiple && isSelected) {\n onUnpick(id);\n } else if (!(multiple && full)) {\n onPick(id);\n }\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLElement>) => {\n if (event.altKey || event.ctrlKey || event.metaKey) {\n return;\n }\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n active.move(event.key === 'ArrowDown' ? 1 : -1);\n } else if ((event.key === 'Home' || event.key === 'End') && !searchable) {\n // In the search box Home/End move the caret.\n event.preventDefault();\n if (event.key === 'Home') {\n active.first();\n } else {\n active.last();\n }\n } else if (event.key === 'Enter' && active.activeId) {\n event.preventDefault();\n choose(active.activeId);\n }\n };\n\n return (\n <div className={cn('flex min-h-0 flex-col gap-3', className)}>\n {searchable ? (\n <div className=\"relative\">\n <Search\n aria-hidden=\"true\"\n className=\"absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n type=\"search\"\n role=\"combobox\"\n aria-expanded=\"true\"\n aria-controls={listboxId}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeDescendant}\n value={text}\n aria-label={t('content.relation.search', { model: target.label })}\n placeholder={t('content.relation.searchPlaceholder')}\n className=\"pl-9\"\n onChange={(event) => setText(event.target.value)}\n onKeyDown={onKeyDown}\n />\n </div>\n ) : null}\n <ul\n id={listboxId}\n role=\"listbox\"\n aria-label={t('content.relation.results')}\n aria-multiselectable={multiple || undefined}\n aria-busy={list.isPending || undefined}\n aria-activedescendant={searchable ? undefined : activeDescendant}\n tabIndex={searchable ? undefined : 0}\n onKeyDown={searchable ? undefined : onKeyDown}\n className={cn(\n 'min-h-0 space-y-0.5 overflow-y-auto rounded-lg outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n listClassName,\n )}\n >\n {items.map((item) => {\n const isSelected = selected.includes(item.id);\n const disabled = multiple && full && !isSelected;\n return (\n <li\n key={item.id}\n id={optionId(item.id)}\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={disabled || undefined}\n data-active={item.id === active.activeId || undefined}\n className={cn(\n 'flex cursor-pointer items-center gap-2 rounded-md px-2 py-2 text-sm select-none data-[active]:bg-accent data-[active]:text-accent-foreground',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n // Focus stays in the search box (or on the listbox) while options are clicked.\n onMouseDown={(event) => event.preventDefault()}\n onPointerMove={() => (item.id === active.activeId ? undefined : active.setActiveId(item.id))}\n onClick={() => choose(item.id)}\n >\n <Check aria-hidden=\"true\" className={cn('size-4 shrink-0', !isSelected && 'invisible')} />\n <span className=\"min-w-0 truncate\">{labelOf(target, item, t('content.untitled'))}</span>\n </li>\n );\n })}\n </ul>\n {list.isPending ? (\n <LoadingState rows={3} />\n ) : list.isError ? (\n <ErrorState error={list.error} onRetry={() => void list.refetch()} />\n ) : items.length === 0 ? (\n <p role=\"status\" className=\"py-4 text-center text-sm text-muted-foreground\">\n {t('content.relation.noResults')}\n </p>\n ) : null}\n </div>\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { Plus } from 'lucide-react';\nimport { useId, useRef, type ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport {\n Sheet,\n SheetBody,\n SheetContent,\n SheetFooter,\n SheetHeader,\n SheetTitle,\n SheetTrigger,\n} from '@/components/ui/sheet';\nimport { useIsMdUp } from '../../hooks/useIsMdUp';\nimport { Results } from './Results';\n\ntype RelationPickerProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** The field's button that opens the picker; absent while nothing more can be linked. */\n trigger: ReactElement | null;\n target: ModelDefinition;\n multiple: boolean;\n /** Linked now. */\n selected: readonly string[];\n /** Never offered (the entry being edited, for self-relations). */\n exclude: readonly string[];\n locale: string | null;\n /** No more may be linked (relation `max`). */\n full: boolean;\n canCreate: boolean;\n /** Links an entry: in single mode the picker then closes, in multi mode it stays open for more. */\n onPick: (id: string) => void;\n onUnpick: (id: string) => void;\n /** Runs once the picker has closed (focus is back on the trigger), to open the create sheet. */\n onCreate: () => void;\n /** Where focus goes on close when the trigger is gone (the relation is full). */\n onFocusFallback: () => void;\n};\n\n/**\n * Finds and links entries of a relation's target model (DESIGN.md \"Dialogs\": pickers). From `md` up it is a\n * modal popover anchored to the field; below, the same body in a bottom sheet. In multi mode every pick\n * links at once and the picker stays open; \"Create new\" closes it before the create sheet opens.\n */\nexport const RelationPicker = ({\n open,\n onOpenChange,\n trigger,\n target,\n multiple,\n selected,\n exclude,\n locale,\n full,\n canCreate,\n onPick,\n onUnpick,\n onCreate,\n onFocusFallback,\n}: RelationPickerProps) => {\n const { t } = useTranslation();\n const isMdUp = useIsMdUp();\n const titleId = useId();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const creatingRef = useRef(false);\n const title = t('content.relation.chooseTitle', { model: target.label });\n\n const pick = (id: string) => {\n onPick(id);\n if (!multiple) {\n onOpenChange(false);\n }\n };\n const startCreate = () => {\n creatingRef.current = true;\n onOpenChange(false);\n };\n /** Runs when the picker has closed: return focus ourselves when handing off or when the trigger is gone. */\n const onCloseAutoFocus = (event: Event) => {\n const creating = creatingRef.current;\n creatingRef.current = false;\n const trigger = triggerRef.current;\n if (!creating && trigger?.isConnected) {\n return;\n }\n event.preventDefault();\n if (trigger?.isConnected) {\n trigger.focus({ preventScroll: true });\n } else {\n onFocusFallback();\n }\n if (creating) {\n onCreate();\n }\n };\n\n const results = (listClassName?: string) => (\n <Results\n target={target}\n locale={locale}\n multiple={multiple}\n selected={selected}\n exclude={exclude}\n full={full}\n onPick={pick}\n onUnpick={onUnpick}\n className=\"flex-1\"\n listClassName={listClassName}\n />\n );\n const actions =\n canCreate || multiple ? (\n <>\n {canCreate ? (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" className=\"mr-auto\" onClick={startCreate}>\n <Plus aria-hidden=\"true\" />\n {t('content.relation.createNew', { model: target.label })}\n </Button>\n ) : null}\n {multiple ? (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => onOpenChange(false)}>\n {t('content.relation.done')}\n </Button>\n ) : null}\n </>\n ) : null;\n\n if (isMdUp) {\n return (\n <Popover open={open} onOpenChange={onOpenChange} modal>\n {trigger ? (\n <PopoverTrigger asChild ref={triggerRef}>\n {trigger}\n </PopoverTrigger>\n ) : null}\n <PopoverContent\n aria-labelledby={titleId}\n align=\"start\"\n collisionPadding={16}\n className=\"flex max-h-(--radix-popover-content-available-height) w-96 flex-col gap-3 p-3\"\n onCloseAutoFocus={onCloseAutoFocus}\n >\n <p id={titleId} className=\"text-sm font-semibold\">\n {title}\n </p>\n {results('max-h-72')}\n {actions ? (\n <div className=\"flex items-center justify-end gap-2 border-t pt-3\">{actions}</div>\n ) : null}\n </PopoverContent>\n </Popover>\n );\n }\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n {trigger ? (\n <SheetTrigger asChild ref={triggerRef}>\n {trigger}\n </SheetTrigger>\n ) : null}\n <SheetContent side=\"bottom\" aria-describedby={undefined} onCloseAutoFocus={onCloseAutoFocus}>\n <SheetHeader>\n <SheetTitle>{title}</SheetTitle>\n </SheetHeader>\n <SheetBody className=\"flex flex-col\">{results()}</SheetBody>\n {actions ? <SheetFooter>{actions}</SheetFooter> : null}\n </SheetContent>\n </Sheet>\n );\n};\n","import { ArrowDown, ArrowUp, Layers, Plus, X } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { IconTile } from '@/components/IconTile';\nimport { Button } from '@/components/ui/button';\nimport { Skeleton } from '@/components/ui/skeleton';\nimport { useFieldsEnvironment } from '../form/context';\nimport { entryTitle, shortId } from '../helpers/titles';\nimport { moveItem, toList } from '../helpers/values';\nimport { useEntryLabels } from '../hooks/useEntryLabels';\nimport type { BuiltInEditorProps } from '../types';\nimport { InlineCreateSheet } from './InlineCreateSheet';\nimport { RelationPicker } from './RelationPicker';\n\n/**\n * `relationPicker`: links to entries of another model, one or many (ordered). Entries are found by their\n * title in a picker anchored to the field; with `allowInlineCreate`, a new one can be created in a sheet\n * without leaving the form.\n */\nexport const RelationField = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const environment = useFieldsEnvironment();\n const { value, onChange, onBlur, readOnly, disabled, definition, field, inputId, labelId, describedBy } =\n props;\n const [searching, setSearching] = useState(false);\n const [creating, setCreating] = useState(false);\n const listRef = useRef<HTMLUListElement>(null);\n const settings = definition.type === 'relation' ? definition.settings : undefined;\n const target = settings ? environment.models.get(settings.target) : undefined;\n const multiple = settings?.cardinality === 'many';\n const ids = toList<string>(value).filter((id): id is string => typeof id === 'string');\n const labels = useEntryLabels(target, ids, environment.locale);\n if (!settings || !target) {\n return <p className=\"text-sm text-destructive\">{t('content.relation.targetMissing')}</p>;\n }\n const editable = !readOnly && !disabled;\n const commit = (next: string[]) => {\n onChange(multiple ? (next.length > 0 ? next : null) : (next[0] ?? null));\n onBlur();\n };\n const add = (id: string) => commit(multiple ? (ids.includes(id) ? ids : [...ids, id]) : [id]);\n const canAddMore = !multiple || settings.max === undefined || ids.length < settings.max;\n const labelFor = (id: string) => {\n const item = labels.byId.get(id);\n return item ? (entryTitle(target, item.data) ?? `${t('content.untitled')} · ${shortId(id)}`) : undefined;\n };\n return (\n <div role=\"group\" aria-labelledby={labelId} aria-describedby={describedBy} className=\"space-y-2\">\n {ids.length > 0 ? (\n <ul ref={listRef} className=\"space-y-2\">\n {ids.map((id, index) => {\n const label = labelFor(id);\n return (\n <li key={id} className=\"flex items-center gap-3 rounded-lg border bg-card p-2 pl-3\">\n <IconTile icon={Layers} />\n <span className=\"min-w-0 flex-1\">\n {label !== undefined ? (\n <span className=\"block truncate text-sm font-semibold\">{label}</span>\n ) : labels.isLoading ? (\n <Skeleton className=\"h-4 w-40\" />\n ) : (\n <span className=\"block truncate text-sm text-destructive\">\n {t('content.relation.missingEntry', { id: shortId(id) })}\n </span>\n )}\n <span className=\"block text-meta text-muted-foreground\">{target.label}</span>\n </span>\n {editable && multiple ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.moveUp', { item: label ?? id, position: index + 1 })}\n disabled={index === 0}\n onClick={() => commit(moveItem(ids, index, index - 1))}\n >\n <ArrowUp aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.moveDown', { item: label ?? id, position: index + 1 })}\n disabled={index === ids.length - 1}\n onClick={() => commit(moveItem(ids, index, index + 1))}\n >\n <ArrowDown aria-hidden=\"true\" />\n </Button>\n </>\n ) : null}\n {editable ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.relation.remove', { item: label ?? id })}\n onClick={() => commit(ids.filter((item) => item !== id))}\n >\n <X aria-hidden=\"true\" />\n </Button>\n ) : null}\n </li>\n );\n })}\n </ul>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.relation.empty')}</p>\n )}\n {editable ? (\n <RelationPicker\n open={searching}\n onOpenChange={setSearching}\n // Stays while the picker is open, so it remains anchored when the last allowed pick fills it.\n trigger={\n canAddMore || searching ? (\n <Button id={inputId} type=\"button\" variant=\"outline\" size=\"sm\">\n <Plus aria-hidden=\"true\" />\n {multiple\n ? t('content.relation.add', { model: target.label })\n : ids.length > 0\n ? t('content.relation.change')\n : t('content.relation.choose', { model: target.label })}\n </Button>\n ) : null\n }\n target={target}\n multiple={multiple}\n selected={ids}\n exclude={environment.entryId && target.id === environment.model.id ? [environment.entryId] : []}\n locale={environment.locale}\n full={!canAddMore}\n // TODO(per-model permissions in `me`): also require `create` on the target model. Until `me` carries\n // per-model permissions, a refusal shows as the server's 403 in the sheet.\n canCreate={field.options.allowInlineCreate === true}\n onPick={add}\n onUnpick={(id) => commit(ids.filter((item) => item !== id))}\n onCreate={() => setCreating(true)}\n // The relation is full and its button gone: focus the last linked entry's Unlink button.\n onFocusFallback={() =>\n listRef.current?.querySelector<HTMLElement>('li:last-child button:last-child')?.focus()\n }\n />\n ) : null}\n {creating ? (\n <InlineCreateSheet\n target={target}\n onClose={() => setCreating(false)}\n onCreated={(id) => {\n setCreating(false);\n add(id);\n }}\n />\n ) : null}\n </div>\n );\n};\n","'use client';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Toggle as TogglePrimitive } from 'radix-ui';\nimport * as React from 'react';\nimport { cn } from '@/helpers/cn';\n\nconst toggleVariants = cva(\n \"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: 'bg-transparent',\n outline: 'border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground',\n },\n size: {\n default: 'h-9 min-w-9 px-2',\n sm: 'h-8 min-w-8 px-1.5',\n lg: 'h-10 min-w-10 px-2.5',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nfunction Toggle({\n className,\n variant,\n size,\n ...props\n}: React.ComponentProps<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>) {\n return (\n <TogglePrimitive.Root\n data-slot=\"toggle\"\n className={cn(toggleVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Toggle, toggleVariants };\n","'use client';\n\nimport { type VariantProps } from 'class-variance-authority';\nimport { ToggleGroup as ToggleGroupPrimitive } from 'radix-ui';\nimport * as React from 'react';\nimport { toggleVariants } from '@/components/ui/toggle';\nimport { cn } from '@/helpers/cn';\n\nconst ToggleGroupContext = React.createContext<VariantProps<typeof toggleVariants>>({\n size: 'default',\n variant: 'default',\n});\n\nfunction ToggleGroup({\n className,\n variant,\n size,\n children,\n ...props\n}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & VariantProps<typeof toggleVariants>) {\n return (\n <ToggleGroupPrimitive.Root\n data-slot=\"toggle-group\"\n data-variant={variant}\n data-size={size}\n className={cn(\n 'group/toggle-group flex w-fit items-center rounded-md data-[variant=outline]:shadow-xs',\n className,\n )}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ variant, size }}>{children}</ToggleGroupContext.Provider>\n </ToggleGroupPrimitive.Root>\n );\n}\n\nfunction ToggleGroupItem({\n className,\n children,\n variant,\n size,\n ...props\n}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants>) {\n const context = React.useContext(ToggleGroupContext);\n\n return (\n <ToggleGroupPrimitive.Item\n data-slot=\"toggle-group-item\"\n data-variant={context.variant || variant}\n data-size={context.size || size}\n className={cn(\n toggleVariants({\n variant: context.variant || variant,\n size: context.size || size,\n }),\n 'min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l',\n className,\n )}\n {...props}\n >\n {children}\n </ToggleGroupPrimitive.Item>\n );\n}\n\nexport { ToggleGroup, ToggleGroupItem };\n","import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';\nimport { choicesOf, fromChoice, toChoice } from '../helpers/choices';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `segmented`: a row of buttons for a boolean or a single-choice enum. Pressing the active one clears it. */\nexport const Segmented = (props: BuiltInEditorProps) => {\n const { labelId, describedBy, value, onChange, onBlur, readOnly, disabled, validation } = props;\n return (\n <ToggleGroup\n type=\"single\"\n variant=\"outline\"\n aria-labelledby={labelId}\n aria-describedby={describedBy}\n aria-invalid={validation.invalid || undefined}\n value={toChoice(value)}\n disabled={disabled || readOnly}\n onValueChange={(choice) => onChange(fromChoice(props, choice))}\n onBlur={onBlur}\n className=\"flex-wrap\"\n >\n {choicesOf(props).map((choice) => (\n <ToggleGroupItem key={choice.value} value={choice.value} className=\"px-3\">\n {choice.label}\n </ToggleGroupItem>\n ))}\n </ToggleGroup>\n );\n};\n","import { ChevronDown } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { ClearButton } from '../ClearButton';\nimport { choicesOf, fromChoice, isMultiple, toChoice } from '../helpers/choices';\nimport { inputAria, stringOption } from '../helpers/props';\nimport { toList } from '../helpers/values';\nimport type { BuiltInEditorProps } from '../types';\n\nconst MultiSelect = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { value, onChange, readOnly, disabled, field } = props;\n const selected = toList<string>(value);\n const choices = choicesOf(props);\n const summary = choices\n .filter((choice) => selected.includes(choice.value))\n .map((choice) => choice.label)\n .join(', ');\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild disabled={disabled || readOnly}>\n <Button variant=\"outline\" {...inputAria(props)} className=\"w-full justify-between font-normal\">\n <span className=\"truncate\">\n {summary || stringOption(props, 'placeholder') || t('content.fields.choose')}\n </span>\n <ChevronDown aria-hidden=\"true\" className=\"opacity-50\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"start\"\n className=\"w-(--radix-dropdown-menu-trigger-width)\"\n aria-label={field.label}\n >\n {choices.map((choice) => (\n <DropdownMenuCheckboxItem\n key={choice.value}\n checked={selected.includes(choice.value)}\n onSelect={(event) => event.preventDefault()}\n onCheckedChange={(checked) =>\n onChange(\n checked\n ? choices\n .map((item) => item.value)\n .filter((item) => item === choice.value || selected.includes(item))\n : selected.filter((item) => item !== choice.value),\n )\n }\n >\n {choice.label}\n </DropdownMenuCheckboxItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n};\n\n/** `select`: a dropdown for an enum (a checkbox menu when the enum allows several values). */\nexport const SelectInput = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { value, onChange, onBlur, readOnly, disabled, field } = props;\n if (isMultiple(props)) {\n return <MultiSelect {...props} />;\n }\n const current = toChoice(value);\n return (\n <div className=\"flex items-center gap-1\">\n <Select\n value={current}\n disabled={disabled || readOnly}\n onValueChange={(choice) => onChange(fromChoice(props, choice))}\n >\n <SelectTrigger {...inputAria(props)} className=\"w-full\" onBlur={onBlur}>\n <SelectValue placeholder={stringOption(props, 'placeholder') ?? t('content.fields.choose')} />\n </SelectTrigger>\n <SelectContent>\n {choicesOf(props).map((choice) => (\n <SelectItem key={choice.value} value={choice.value}>\n {choice.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {current && !field.required && !readOnly ? (\n <ClearButton label={field.label} disabled={disabled} onClear={() => onChange(null)} />\n ) : null}\n </div>\n );\n};\n","import { useTranslation } from 'react-i18next';\nimport { cn } from '@/helpers/cn';\nimport type { SeoCounter } from '../helpers';\n\ntype CounterProps = { counter: SeoCounter };\n\n/** Characters used against the soft maximum, shown near and over it. Never an error: nothing is enforced. */\nexport const Counter = ({ counter }: CounterProps) => {\n const { t } = useTranslation();\n return (\n <p className={cn('text-meta tabular-nums', counter.over ? 'text-warning' : 'text-muted-foreground')}>\n {t(counter.over ? 'seo.field.counterOver' : 'seo.field.counter', {\n count: counter.count,\n max: counter.max,\n })}\n </p>\n );\n};\n","import type { Locale } from '@shapio/client';\nimport {\n resolveSeo,\n seoComponentDefinition,\n seoDefaultsForLocale,\n SEO_DESCRIPTION_SOFT_MAX,\n SEO_FIELD_IDS,\n SEO_TITLE_SOFT_MAX,\n type ComponentDefinition,\n type SeoDefaults,\n type SeoFieldKey,\n type SeoKeys,\n} from '@shapio/schema';\n\n/** A counter shows once the text is this close to its soft maximum (and stays while it is over). */\nexport const SEO_COUNTER_WINDOW = 10;\n\nconst SOFT_MAX_BY_FIELD_ID: Readonly<Record<string, number>> = {\n [SEO_FIELD_IDS.title]: SEO_TITLE_SOFT_MAX,\n [SEO_FIELD_IDS.description]: SEO_DESCRIPTION_SOFT_MAX,\n};\n\nexport type SeoCounter = { count: number; max: number; over: boolean };\n\n/**\n * The length counter under the SEO title or description (by stable field ID), or null when hidden: the field\n * has no soft maximum, or its text is more than `SEO_COUNTER_WINDOW` characters short of it.\n */\nexport const seoCounterOf = (fieldId: string, value: unknown): SeoCounter | null => {\n const max = SOFT_MAX_BY_FIELD_ID[fieldId];\n if (max === undefined) {\n return null;\n }\n const count = typeof value === 'string' ? [...value].length : 0;\n return count >= max - SEO_COUNTER_WINDOW ? { count, max, over: count > max } : null;\n};\n\nconst BUILT_IN_TYPES = new Map(seoComponentDefinition().fields.map((field) => [field.id, field.type]));\n\n/**\n * Where each built-in SEO field sits in a value of `component` (its API IDs may have been renamed): looked\n * up by stable ID; a removed or retyped field is left out, like the server's resolver does.\n */\nexport const seoKeysOf = (component: ComponentDefinition): SeoKeys => {\n const keys: SeoKeys = {};\n for (const [key, id] of Object.entries(SEO_FIELD_IDS) as [SeoFieldKey, string][]) {\n const field = component.fields.find((candidate) => candidate.id === id && !candidate.deprecated);\n if (field && field.type === BUILT_IN_TYPES.get(id)) {\n keys[key] = field.apiKey;\n }\n }\n return keys;\n};\n\n/** The locale, its configured fallbacks, then the default locale: the order delivery reads them in. */\nexport const localeChainOf = (locales: readonly Locale[], code: string | null): string[] => {\n const fallbackLocale = locales.find((locale) => locale.isDefault)?.code;\n const start = code ?? fallbackLocale;\n const configured = locales.find((locale) => locale.code === start)?.fallbacks ?? [];\n const chain = [start, ...configured, fallbackLocale].filter(\n (entry): entry is string => entry !== undefined && locales.some((locale) => locale.code === entry),\n );\n return chain.filter((entry, index) => chain.indexOf(entry) === index);\n};\n\nexport type SeoPreview = {\n /** The title as search results show it (through the site's template), or null when there is none. */\n title: string | null;\n description: string | null;\n /** The site's name for the result's URL line, when the defaults set one. */\n siteName: string | null;\n};\n\ntype SeoPreviewInput = {\n value: unknown;\n component: ComponentDefinition;\n defaults: SeoDefaults;\n localeChain: readonly string[];\n /** The entry's own title, used when the SEO title is empty. */\n fallbackTitle: unknown;\n};\n\n/** What a search result would show for this SEO value: the same rules as delivery's `seo=resolved`. */\nexport const seoPreviewOf = ({\n value,\n component,\n defaults,\n localeChain,\n fallbackTitle,\n}: SeoPreviewInput): SeoPreview => {\n const keys = seoKeysOf(component);\n const localeDefaults = seoDefaultsForLocale(defaults, localeChain);\n const resolved = resolveSeo(value, {\n defaults: localeDefaults,\n image: null,\n fallbackTitle: typeof fallbackTitle === 'string' ? fallbackTitle : null,\n keys,\n });\n const text = (key: SeoFieldKey) => {\n const entry = keys[key] === undefined ? undefined : resolved[keys[key]];\n return typeof entry === 'string' && entry.trim() !== '' ? entry : null;\n };\n return {\n title: keys.title === undefined ? null : text('title'),\n description: text('description'),\n siteName: localeDefaults.siteName ?? null,\n };\n};\n","import { effectiveTitleField, type ComponentDefinition } from '@shapio/schema';\nimport { useMemo } from 'react';\nimport { useMe } from '@/api/auth';\nimport { useLocales } from '@/api/locales';\nimport { useSiteSeoDefaults } from '@/api/seo';\nimport { useEntryForm, useFieldsEnvironment } from '../../form/context';\nimport { localeChainOf, seoPreviewOf, type SeoPreview } from '../helpers';\n\nexport type SeoPreviewWithSlug = SeoPreview & {\n /** The URL line: the site's SEO name (else its admin name) and the entry's slug, when it has one. */\n urlLine: string;\n};\n\n/**\n * The search-result preview of an SEO value in the entry being edited: the entry's title and slug from the\n * form, the site's defaults for the locale being edited (through its fallback chain).\n */\nexport const useSeoPreview = (component: ComponentDefinition, value: unknown): SeoPreviewWithSlug => {\n const { model, locale } = useFieldsEnvironment();\n const defaults = useSiteSeoDefaults();\n const locales = useLocales().data;\n const siteName = useMe().data?.site.name ?? '';\n const titleKey = effectiveTitleField(model)?.apiKey;\n const slugKey = model.fields.find((field) => field.type === 'slug' && !field.deprecated)?.apiKey;\n const fallbackTitle = useEntryForm((state) => (titleKey ? state.values[titleKey] : undefined));\n const slug = useEntryForm((state) => (slugKey ? state.values[slugKey] : undefined));\n return useMemo(() => {\n const preview = seoPreviewOf({\n value,\n component,\n defaults,\n localeChain: localeChainOf(locales ?? [], locale),\n fallbackTitle,\n });\n const host = preview.siteName ?? siteName;\n const urlLine = typeof slug === 'string' && slug !== '' ? `${host} › ${slug}` : host;\n return { ...preview, urlLine };\n }, [value, component, defaults, locales, locale, fallbackTitle, siteName, slug]);\n};\n","import { useId } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { SeoPreviewWithSlug } from '../hooks/useSeoPreview';\n\ntype PreviewProps = { preview: SeoPreviewWithSlug; noindex: boolean };\n\n/** How a search result could show the entry: URL line, title (through the site's template), description. */\nexport const Preview = ({ preview, noindex }: PreviewProps) => {\n const { t } = useTranslation();\n const headingId = useId();\n return (\n <section aria-labelledby={headingId} className=\"space-y-2 rounded-lg border bg-muted/40 p-4\">\n <h4 id={headingId} className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n {t('seo.field.preview')}\n </h4>\n <div className=\"min-w-0 space-y-0.5\">\n <p className=\"truncate text-meta text-muted-foreground\">{preview.urlLine}</p>\n <p className=\"line-clamp-2 text-base font-semibold break-words text-link\">\n {preview.title ?? t('seo.field.noTitle')}\n </p>\n {preview.description ? (\n <p className=\"line-clamp-3 text-sm break-words text-muted-foreground\">{preview.description}</p>\n ) : null}\n </div>\n {noindex ? <p className=\"text-meta text-warning\">{t('seo.field.noindex')}</p> : null}\n </section>\n );\n};\n","import { isSeoField, type ComponentDefinition, type FieldDefinition } from '@shapio/schema';\nimport { useCallback, useMemo } from 'react';\nimport { ComponentField } from '../ComponentField';\nimport { ComponentItemFields } from '../ComponentItemFields';\nimport { useFieldsEnvironment } from '../form/context';\nimport { newComponentItem } from '../helpers/formValues';\nimport { isRecord, type ItemValues } from '../helpers/values';\nimport type { BuiltInEditorProps } from '../types';\nimport { Counter } from './Counter';\nimport { seoCounterOf, seoKeysOf } from './helpers';\nimport { useSeoPreview } from './hooks/useSeoPreview';\nimport { Preview } from './Preview';\n\ntype SeoGroupProps = BuiltInEditorProps & { component: ComponentDefinition };\n\nconst renderCounter = (field: FieldDefinition, value: unknown) => {\n const counter = seoCounterOf(field.id, value);\n return counter ? <Counter counter={counter} /> : null;\n};\n\n/** The SEO group: its fields shown at once (an empty value starts on the first edit), counters, preview. */\nconst SeoGroup = ({ component, value, onChange, path }: SeoGroupProps) => {\n const item = useMemo(\n () => (isRecord(value) ? value : newComponentItem(component, false)),\n [value, component],\n );\n const onItemChange = useCallback((next: ItemValues) => onChange(next), [onChange]);\n const preview = useSeoPreview(component, value);\n const noindexKey = seoKeysOf(component).noindex;\n return (\n <div className=\"space-y-4 rounded-xl border bg-card p-5\">\n <ComponentItemFields\n component={component}\n item={item}\n onItemChange={onItemChange}\n path={path}\n renderFieldFooter={renderCounter}\n />\n <Preview preview={preview} noindex={noindexKey !== undefined && item[noindexKey] === true} />\n </div>\n );\n};\n\n/**\n * `seoEditor`: the built-in SEO component's fields with length counters on title and description and a\n * search-result preview. Any other component field (the editor chosen by hand) gets the plain component\n * editor.\n */\nexport const SeoField = (props: BuiltInEditorProps) => {\n const { components } = useFieldsEnvironment();\n const { definition } = props;\n const component =\n definition.type === 'component' && isSeoField(definition)\n ? components.get(definition.settings.component)\n : undefined;\n return component ? <SeoGroup {...props} component={component} /> : <ComponentField {...props} />;\n};\n","/** Text → `lower-case-words-with-hyphens` (the `slug` format), dropping accents and punctuation. */\nexport const slugify = (text: string): string =>\n text\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n","import { Link2, Link2Off } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { useSiblingValues } from '../form/context';\nimport { inputAria, stringOption, textValue } from '../helpers/props';\nimport { slugify } from '../helpers/slugify';\nimport type { BuiltInEditorProps } from '../types';\n\n/** The text of the field a slug is generated from (`settings.sourceFieldId`, usually the title). */\nconst useSourceText = (props: BuiltInEditorProps): string | undefined => {\n const siblings = useSiblingValues();\n const sourceId = props.definition.type === 'slug' ? props.definition.settings.sourceFieldId : undefined;\n const source = siblings?.definition.fields.find((field) => field.id === sourceId);\n if (!source) {\n return undefined;\n }\n const value = siblings?.values[source.apiKey];\n return typeof value === 'string' ? value : '';\n};\n\n/**\n * `slugInput`: a URL slug that follows its source field (e.g. the title) until someone edits it by hand.\n * The lock button switches between following the source and keeping the slug as typed.\n */\nexport const SlugInput = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { value, onChange, onBlur, readOnly, disabled } = props;\n const sourceText = useSourceText(props);\n const text = textValue(value);\n const [following, setFollowing] = useState(\n () => sourceText !== undefined && (text === '' || text === slugify(sourceText)),\n );\n const lastSource = useRef(sourceText);\n useEffect(() => {\n if (sourceText === undefined || sourceText === lastSource.current) {\n return;\n }\n lastSource.current = sourceText;\n if (following && !readOnly) {\n const next = slugify(sourceText);\n onChange(next === '' ? null : next);\n }\n }, [sourceText, following, readOnly, onChange]);\n return (\n <div className=\"flex items-center gap-1\">\n <Input\n {...inputAria(props)}\n value={text}\n placeholder={stringOption(props, 'placeholder')}\n readOnly={readOnly}\n disabled={disabled}\n spellCheck={false}\n className=\"font-mono text-sm\"\n onChange={(event) => {\n setFollowing(false);\n onChange(event.target.value === '' ? null : event.target.value);\n }}\n onBlur={() => {\n // Tidy what was typed into the slug format when leaving the field.\n if (text && slugify(text) !== text) {\n onChange(slugify(text) || null);\n }\n onBlur();\n }}\n />\n {sourceText !== undefined && !readOnly ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-pressed={following}\n aria-label={following ? t('content.fields.slug.unlink') : t('content.fields.slug.link')}\n title={following ? t('content.fields.slug.unlink') : t('content.fields.slug.link')}\n disabled={disabled}\n onClick={() => {\n if (!following) {\n const next = slugify(sourceText);\n onChange(next === '' ? null : next);\n }\n setFollowing(!following);\n }}\n >\n {following ? <Link2 aria-hidden=\"true\" /> : <Link2Off aria-hidden=\"true\" />}\n </Button>\n ) : null}\n </div>\n );\n};\n","import { useTranslation } from 'react-i18next';\nimport { Textarea as TextareaControl } from '@/components/ui/textarea';\nimport { inputAria, numberOption, stringOption, textValue } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\nconst DEFAULT_ROWS = 4;\n\n/** `textarea`: several lines of plain text, with a character count when the field has a maximum. */\nexport const Textarea = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { inputId, value, onChange, onBlur, readOnly, disabled, definition } = props;\n const text = textValue(value);\n const maxLength = 'maxLength' in definition.settings ? definition.settings.maxLength : undefined;\n const countId = `${inputId}-count`;\n return (\n <div className=\"space-y-1\">\n <TextareaControl\n {...inputAria(props, maxLength ? countId : undefined)}\n rows={numberOption(props, 'rows') ?? DEFAULT_ROWS}\n value={text}\n placeholder={stringOption(props, 'placeholder')}\n readOnly={readOnly}\n disabled={disabled}\n onChange={(event) => onChange(event.target.value === '' ? null : event.target.value)}\n onBlur={onBlur}\n />\n {maxLength ? (\n <p id={countId} className=\"text-right text-meta text-muted-foreground tabular-nums\">\n {t('content.fields.characterCount', { count: text.length, max: maxLength })}\n </p>\n ) : null}\n </div>\n );\n};\n","import { Input } from '@/components/ui/input';\nimport { inputAria, stringOption, textValue } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\nconst INPUT_TYPES: Partial<Record<string, 'email' | 'url'>> = { email: 'email', url: 'url' };\n\n/** `textInput`: one line of text (string, email, URL, UID). */\nexport const TextInput = (props: BuiltInEditorProps) => {\n const { value, onChange, onBlur, readOnly, disabled, definition } = props;\n const maxLength = 'maxLength' in definition.settings ? definition.settings.maxLength : undefined;\n return (\n <Input\n {...inputAria(props)}\n type={INPUT_TYPES[definition.type] ?? 'text'}\n value={textValue(value)}\n placeholder={stringOption(props, 'placeholder')}\n maxLength={maxLength}\n readOnly={readOnly}\n disabled={disabled}\n spellCheck={definition.type === 'string'}\n onChange={(event) => onChange(event.target.value === '' ? null : event.target.value)}\n onBlur={onBlur}\n />\n );\n};\n","import { Input } from '@/components/ui/input';\nimport { ClearButton } from '../ClearButton';\nimport { inputAria, numberOption, textValue } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\nconst SECONDS_PER_MINUTE = 60;\n\n/** `timePicker`: a time of day stored as `HH:mm` (or `HH:mm:ss`), with an optional minute step. */\nexport const TimeInput = (props: BuiltInEditorProps) => {\n const { value, onChange, onBlur, readOnly, disabled, field } = props;\n const text = textValue(value);\n return (\n <div className=\"flex items-center gap-1\">\n <Input\n {...inputAria(props)}\n type=\"time\"\n value={text}\n step={(numberOption(props, 'stepMinutes') ?? 1) * SECONDS_PER_MINUTE}\n readOnly={readOnly}\n disabled={disabled}\n className=\"w-auto\"\n onChange={(event) => onChange(event.target.value === '' ? null : event.target.value)}\n onBlur={onBlur}\n />\n {text && !readOnly ? (\n <ClearButton label={field.label} disabled={disabled} onClear={() => onChange(null)} />\n ) : null}\n </div>\n );\n};\n","import { Switch } from '@/components/ui/switch';\nimport { inputAria } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `toggle`: an on/off switch for booleans. */\nexport const Toggle = (props: BuiltInEditorProps) => {\n const { value, onChange, onBlur, readOnly, disabled } = props;\n return (\n <Switch\n {...inputAria(props)}\n checked={value === true}\n disabled={disabled || readOnly}\n onCheckedChange={(checked) => onChange(checked)}\n onBlur={onBlur}\n />\n );\n};\n","import type { EditorDefinition } from '@shapio/editor-sdk';\nimport {\n DEFAULT_EDITORS,\n EDITOR_CATALOGUE,\n isCustomEditorId,\n SEO_EDITOR_ID,\n type FieldDefinition,\n} from '@shapio/schema';\nimport { lazy } from 'react';\nimport { CheckboxGroup } from './CheckboxGroup';\nimport { CheckboxInput } from './CheckboxInput';\nimport { ColorInput } from './ColorInput';\nimport { ComponentField } from './ComponentField';\nimport { DateInput } from './DateInput';\nimport { DateTimeInput } from './DateTimeInput';\nimport { DynamicZoneField } from './DynamicZoneField';\nimport { JsonEditor } from './JsonEditor';\nimport { MediaField } from './MediaField';\nimport { NumberInput } from './NumberInput';\nimport { RadioInput } from './RadioInput';\nimport { RelationField } from './RelationField';\nimport { Segmented } from './Segmented';\nimport { SelectInput } from './SelectInput';\nimport { SeoField } from './SeoField';\nimport { SlugInput } from './SlugInput';\nimport { Textarea } from './Textarea';\nimport { TextInput } from './TextInput';\nimport { TimeInput } from './TimeInput';\nimport { Toggle } from './Toggle';\nimport type { BuiltInEditor } from './types';\n\n/** Tiptap and ProseMirror are most of the editor code: loaded only when a form has a rich-text field. */\nconst RichTextField = lazy(() =>\n import('./RichTextField').then((module) => ({ default: module.RichTextField })),\n);\n\n/** CodeMirror and its language packs: loaded only when a form has a code field. */\nconst CodeEditor = lazy(() => import('./CodeEditor').then((module) => ({ default: module.CodeEditor })));\n\n/** Built-in editors by catalogue ID (`EDITOR_CATALOGUE` in @shapio/schema). */\nexport const BUILT_IN_EDITORS: Readonly<Record<string, BuiltInEditor>> = {\n textInput: { component: TextInput, labelling: 'input' },\n textarea: { component: Textarea, labelling: 'input' },\n color: { component: ColorInput, labelling: 'input' },\n richText: { component: RichTextField, labelling: 'group' },\n numberInput: { component: NumberInput, labelling: 'input' },\n toggle: { component: Toggle, labelling: 'input' },\n checkbox: { component: CheckboxInput, labelling: 'input' },\n segmented: { component: Segmented, labelling: 'group' },\n select: { component: SelectInput, labelling: 'input' },\n radio: { component: RadioInput, labelling: 'group' },\n checkboxGroup: { component: CheckboxGroup, labelling: 'group' },\n datePicker: { component: DateInput, labelling: 'input' },\n dateTimePicker: { component: DateTimeInput, labelling: 'input' },\n timePicker: { component: TimeInput, labelling: 'input' },\n slugInput: { component: SlugInput, labelling: 'input' },\n jsonEditor: { component: JsonEditor, labelling: 'input' },\n codeEditor: { component: CodeEditor, labelling: 'group' },\n mediaPicker: { component: MediaField, labelling: 'group' },\n relationPicker: { component: RelationField, labelling: 'group' },\n componentEditor: { component: ComponentField, labelling: 'group' },\n dynamicZoneEditor: { component: DynamicZoneField, labelling: 'group' },\n [SEO_EDITOR_ID]: { component: SeoField, labelling: 'group' },\n};\n\n/** The built-in editor for a field: its chosen one when compatible, otherwise its data type's default. */\nexport const builtInEditorFor = (field: FieldDefinition): BuiltInEditor => {\n const chosen = BUILT_IN_EDITORS[field.editor.id];\n const compatible = EDITOR_CATALOGUE.get(field.editor.id)?.dataTypes.includes(field.type) ?? false;\n const fallback = BUILT_IN_EDITORS[DEFAULT_EDITORS[field.type]];\n if (!fallback) {\n throw new Error(`No built-in editor for data type ${field.type}`);\n }\n return chosen && compatible ? chosen : fallback;\n};\n\nexport type ResolvedEditor =\n | { kind: 'builtIn'; editor: BuiltInEditor; missingCustomId: string | undefined }\n | { kind: 'runtime'; definition: EditorDefinition; fallback: BuiltInEditor };\n\n/** Which editor renders a field: a project's custom editor when installed and compatible, else a built-in. */\nexport const resolveEditor = (\n field: FieldDefinition,\n runtimeEditors: ReadonlyMap<string, EditorDefinition>,\n): ResolvedEditor => {\n const builtIn = builtInEditorFor(field);\n if (!isCustomEditorId(field.editor.id)) {\n return { kind: 'builtIn', editor: builtIn, missingCustomId: undefined };\n }\n const custom = runtimeEditors.get(field.editor.id);\n if (custom && (custom.dataTypes as readonly string[]).includes(field.type)) {\n return { kind: 'runtime', definition: custom, fallback: builtIn };\n }\n return { kind: 'builtIn', editor: builtIn, missingCustomId: field.editor.id };\n};\n","import type { FieldEditorProps } from '@shapio/editor-sdk';\nimport type { FieldDefinition, SchemaDefinition } from '@shapio/schema';\nimport { useCallback, useMemo } from 'react';\nimport { useEntryForm, useFieldsEnvironment } from '../form/context';\nimport { clientIssuesOf } from '../helpers/clientValidation';\nimport { fieldDomId } from '../helpers/domIds';\nimport { toEditorContext, toEditorField, toEditorModel } from '../helpers/editorContext';\nimport { describeIssue } from '../helpers/issues';\nimport { resolveEditor } from '../registry';\nimport type { BuiltInEditorProps, EditorAppearance } from '../types';\n\nexport type FieldControlOptions = {\n field: FieldDefinition;\n /** The model or component the field belongs to. */\n owner: SchemaDefinition;\n value: unknown;\n onChange: (value: unknown) => void;\n /** JSON pointer of the value, e.g. `/hero/title` (issues use the same paths). */\n path: string;\n appearance?: EditorAppearance;\n};\n\n/** Component and dynamic-zone editors render nested fields, which show their own issues. */\nconst NESTING_TYPES: ReadonlySet<string> = new Set(['component', 'dynamiczone']);\n\nconst useFieldMessages = (field: FieldDefinition, value: unknown, path: string): string[] => {\n const serverIssues = useEntryForm((state) => state.issues);\n const revealed = useEntryForm((state) => state.revealAll || state.touched.has(path));\n return useMemo(() => {\n const nesting = NESTING_TYPES.has(field.type);\n const server = serverIssues.filter(\n (issue) =>\n issue.path === path ||\n (issue.path.startsWith(`${path}/`) && (!nesting || issue.path === `${path}/__component`)),\n );\n const client = revealed\n ? clientIssuesOf(field, value).filter((issue) => !server.some((known) => known.code === issue.code))\n : [];\n return [...new Set([...server, ...client].map((issue) => describeIssue(issue, field)))];\n }, [field, value, path, serverIssues, revealed]);\n};\n\n/**\n * Everything a field's chrome needs, whatever it looks like (a labelled form row, a canvas block, a\n * property chip): which editor renders it (a project's custom editor or a built-in), the props for it, the\n * DOM ids that tie label, description and errors together, and the messages to show (server issues for this\n * path, plus client-side checks once the field was left or a save was attempted).\n */\nexport const useFieldControl = ({\n field,\n owner,\n value,\n onChange,\n path,\n appearance = 'form',\n}: FieldControlOptions) => {\n const environment = useFieldsEnvironment();\n const touch = useEntryForm((state) => state.touch);\n const messages = useFieldMessages(field, value, path);\n const onBlur = useCallback(() => touch(path), [touch, path]);\n const resolved = useMemo(\n () => resolveEditor(field, environment.runtimeEditors),\n [field, environment.runtimeEditors],\n );\n const inputId = fieldDomId(environment.idPrefix, path);\n const labelId = `${inputId}-label`;\n const descriptionId = field.description ? `${inputId}-description` : undefined;\n const errorsId = messages.length > 0 ? `${inputId}-errors` : undefined;\n const describedBy = [descriptionId, errorsId].filter(Boolean).join(' ') || undefined;\n const editorField = useMemo(() => toEditorField(field), [field]);\n const editorModel = useMemo(() => toEditorModel(owner), [owner]);\n const context = useMemo(() => toEditorContext(environment), [environment]);\n const builtInProps: BuiltInEditorProps = {\n inputId,\n labelId,\n describedBy,\n value: value ?? null,\n onChange,\n onBlur,\n validation: { errors: messages, invalid: messages.length > 0 },\n readOnly: environment.readOnly,\n disabled: environment.disabled,\n field: editorField,\n model: editorModel,\n context,\n definition: field,\n path,\n appearance,\n };\n // Custom editors get exactly the public contract: no definition internals, no form paths, no appearance.\n const { definition: _definition, path: _path, appearance: _appearance, ...contractProps } = builtInProps;\n const builtIn = resolved.kind === 'builtIn' ? resolved.editor : resolved.fallback;\n return {\n resolved,\n builtIn,\n builtInProps,\n contractProps: contractProps as FieldEditorProps,\n /** How the label points at the editor: `<label for>` (one input) or `aria-labelledby` (a group). */\n labelling: resolved.kind === 'runtime' ? ('input' as const) : builtIn.labelling,\n inputId,\n labelId,\n descriptionId,\n errorsId,\n messages,\n };\n};\n\nexport type FieldControlState = ReturnType<typeof useFieldControl>;\n","import { useQuery } from '@tanstack/react-query';\nimport { adminApi } from './client';\nimport { queryKeys } from './queryKeys';\n\n/** Custom field editors the project installed. Changes only with a server restart, so read once. */\nexport const useEditorManifest = () =>\n useQuery({\n queryKey: queryKeys.editorManifest,\n queryFn: () => adminApi.extensions.editors(),\n staleTime: Infinity,\n meta: { silent: true },\n });\n","import type { EditorManifest } from '@shapio/client';\nimport { EDITOR_CONTRACT_VERSION, isEditorDefinition, type EditorDefinition } from '@shapio/editor-sdk';\nimport { apiBaseUrl } from '@/api/client';\nimport { logError } from '@/helpers/reportError';\n\n/**\n * Loads the project's custom field editors (ADR 0009). Each manifest entry is an ES module served by the\n * API; it imports `react` and `@shapio/editor-sdk` as bare specifiers, which the admin's import map resolves\n * to the admin's own instances. Any export that is an editor definition registers that editor.\n */\nexport type EditorLoadProblem = {\n file: string;\n reason: 'importFailed' | 'noEditor' | 'contractVersion' | 'duplicateId';\n detail?: string;\n};\n\nexport type RuntimeEditors = {\n editors: ReadonlyMap<string, EditorDefinition>;\n problems: readonly EditorLoadProblem[];\n};\n\nexport const NO_RUNTIME_EDITORS: RuntimeEditors = { editors: new Map(), problems: [] };\n\n/** The module's URL: manifest paths are relative to the server's base URL (`{BASE_PATH}/`). */\nexport const editorModuleUrl = (path: string, base: string = apiBaseUrl()) =>\n new URL(path.replace(/^\\/+/, ''), base).href;\n\ntype ImportModule = (url: string) => Promise<Record<string, unknown>>;\n\nconst importModule: ImportModule = (url) =>\n import(/* @vite-ignore */ url) as Promise<Record<string, unknown>>;\n\nexport const loadRuntimeEditors = async (\n manifest: EditorManifest,\n load: ImportModule = importModule,\n): Promise<RuntimeEditors> => {\n const editors = new Map<string, EditorDefinition>();\n const problems: EditorLoadProblem[] = [];\n for (const item of manifest.items) {\n let module: Record<string, unknown>;\n try {\n module = await load(editorModuleUrl(item.path));\n } catch (error) {\n logError(error, `loading custom editor ${item.file}`);\n problems.push({ file: item.file, reason: 'importFailed', detail: String(error) });\n continue;\n }\n const definitions = Object.values(module).filter(isEditorDefinition);\n if (definitions.length === 0) {\n problems.push({ file: item.file, reason: 'noEditor' });\n }\n for (const definition of definitions) {\n if (definition.contractVersion !== EDITOR_CONTRACT_VERSION) {\n problems.push({ file: item.file, reason: 'contractVersion', detail: definition.id });\n } else if (editors.has(definition.id)) {\n problems.push({ file: item.file, reason: 'duplicateId', detail: definition.id });\n } else {\n editors.set(definition.id, definition);\n }\n }\n }\n return { editors, problems };\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { useEditorManifest } from '@/api/editors';\nimport { loadRuntimeEditors, NO_RUNTIME_EDITORS, type RuntimeEditors } from './loader';\n\n/** The project's custom editors, imported once per session (they change only with a server restart). */\nexport const useRuntimeEditors = (): RuntimeEditors & { isLoading: boolean } => {\n const manifest = useEditorManifest();\n const modules = useQuery({\n queryKey: ['extensions', 'editors', 'modules', manifest.data ?? null],\n queryFn: () => loadRuntimeEditors(manifest.data ?? { items: [] }),\n enabled: manifest.data !== undefined,\n staleTime: Infinity,\n gcTime: Infinity,\n meta: { silent: true },\n });\n return {\n ...(modules.data ?? NO_RUNTIME_EDITORS),\n isLoading: manifest.isPending || (manifest.data !== undefined && modules.isPending),\n };\n};\n","import {\n collectionQueryName,\n isModelDefinition,\n MUTATION_PREFIXES,\n routeKeyOf,\n toTypeName,\n type FieldDefinition,\n type SchemaDefinition,\n} from '@shapio/schema';\n\n/**\n * The API shapes a definition produces, derived from the registry naming helpers in `@shapio/schema`\n * (`routeKeyOf`, `toTypeName`, `collectionQueryName`, `MUTATION_PREFIXES`), the same names the server's\n * OpenAPI and GraphQL builders use. Previews of a definition being edited, before it exists on the server.\n */\nexport type DefinitionLookup = ReadonlyMap<string, SchemaDefinition>;\n\nexport type RestEndpoint = {\n method: 'GET' | 'POST' | 'PUT' | 'DELETE';\n path: string;\n scope: 'delivery' | 'admin';\n};\n\nconst liveFields = (definition: SchemaDefinition) => definition.fields.filter((field) => !field.deprecated);\n\nexport const restEndpoints = (definition: SchemaDefinition): RestEndpoint[] => {\n if (!isModelDefinition(definition)) {\n return [];\n }\n const delivery = `/api/content/${routeKeyOf(definition)}`;\n const admin = `/api/admin/content/${definition.apiKey}`;\n const collection = definition.kind === 'collection';\n return [\n { method: 'GET', path: delivery, scope: 'delivery' },\n ...(collection ? [{ method: 'GET' as const, path: `${delivery}/{id}`, scope: 'delivery' as const }] : []),\n { method: 'GET', path: admin, scope: 'admin' },\n { method: 'POST', path: admin, scope: 'admin' },\n { method: 'GET', path: `${admin}/{id}`, scope: 'admin' },\n { method: 'PUT', path: `${admin}/{id}`, scope: 'admin' },\n { method: 'DELETE', path: `${admin}/{id}`, scope: 'admin' },\n { method: 'POST', path: `${admin}/{id}/publish`, scope: 'admin' },\n { method: 'POST', path: `${admin}/{id}/unpublish`, scope: 'admin' },\n ];\n};\n\n/** Delivery's default rich-text shape (`richText=json`); `html` and `both` add the rendered HTML. */\nconst RICH_TEXT_SAMPLE = {\n format: 'shapio-richtext',\n version: 1,\n doc: { type: 'doc', content: [] },\n};\n\nconst MEDIA_SAMPLE = { id: '<uuid>', url: '<url>', mimeType: '<mime type>', alt: '' };\n\n/** Nesting depth for component samples (components inside components show as `{}` below it). */\nconst MAX_SAMPLE_DEPTH = 2;\n\nconst sampleValue = (field: FieldDefinition, lookup: DefinitionLookup, depth: number): unknown => {\n const many = (multiple: boolean, value: unknown) => (multiple ? [value] : value);\n switch (field.type) {\n case 'number':\n case 'integer':\n return 0;\n case 'boolean':\n return false;\n case 'json':\n return {};\n case 'richtext':\n return RICH_TEXT_SAMPLE;\n case 'media':\n return many(field.settings.multiple, MEDIA_SAMPLE);\n case 'enum':\n return many(field.settings.multiple, field.settings.values[0]?.value ?? '');\n case 'relation':\n return many(field.settings.cardinality === 'many', '<entry id>');\n case 'component': {\n const component = lookup.get(field.settings.component);\n return many(field.settings.repeatable, component ? sampleObject(component, lookup, depth + 1) : {});\n }\n case 'dynamiczone':\n return field.settings.components.slice(0, 1).flatMap((id) => {\n const component = lookup.get(id);\n return component\n ? [{ __component: component.apiKey, ...sampleObject(component, lookup, depth + 1) }]\n : [];\n });\n default:\n return `<${field.type}>`;\n }\n};\n\nconst sampleObject = (\n definition: SchemaDefinition,\n lookup: DefinitionLookup,\n depth: number,\n): Record<string, unknown> =>\n depth > MAX_SAMPLE_DEPTH\n ? {}\n : Object.fromEntries(\n liveFields(definition).map((field) => [field.apiKey, sampleValue(field, lookup, depth)]),\n );\n\nconst SYSTEM_SAMPLE = {\n id: '<uuid>',\n locale: '<locale>',\n createdAt: '<datetime>',\n updatedAt: '<datetime>',\n publishedAt: '<datetime>',\n};\n\n/** An example delivery response (`GET /api/content/:routeKey`), as pretty JSON. */\nexport const restResponseSample = (definition: SchemaDefinition, lookup: DefinitionLookup): string => {\n const item = { ...SYSTEM_SAMPLE, ...sampleObject(definition, lookup, 0) };\n if (!isModelDefinition(definition)) {\n return JSON.stringify(sampleObject(definition, lookup, 0), null, 2);\n }\n const meta = { locale: '<locale>', snapshot: 0 };\n const body =\n definition.kind === 'collection'\n ? { data: [item], meta: { ...meta, pagination: { page: 1, pageSize: 25, pageCount: 1, total: 1 } } }\n : { data: item, meta };\n return JSON.stringify(body, null, 2);\n};\n\nconst listOf = (multiple: boolean, type: string) => (multiple ? `[${type}!]` : type);\n\nconst graphqlFieldType = (owner: SchemaDefinition, field: FieldDefinition, lookup: DefinitionLookup) => {\n const nameOf = (id: string) => {\n const target = lookup.get(id);\n return target ? toTypeName(target.apiKey) : 'JSON';\n };\n switch (field.type) {\n case 'number':\n return 'Float';\n case 'integer':\n return 'Int53';\n case 'boolean':\n return 'Boolean';\n case 'json':\n return 'JSON';\n case 'richtext':\n return 'RichText';\n case 'media':\n return listOf(field.settings.multiple, 'Media');\n case 'enum':\n return listOf(field.settings.multiple, `${toTypeName(owner.apiKey)}${toTypeName(field.apiKey)}Enum`);\n case 'relation':\n return listOf(field.settings.cardinality === 'many', nameOf(field.settings.target));\n case 'component':\n return listOf(field.settings.repeatable, nameOf(field.settings.component));\n case 'dynamiczone':\n return `[${toTypeName(owner.apiKey)}${toTypeName(field.apiKey)}Zone!]`;\n default:\n return 'String';\n }\n};\n\nconst READ_ARGS =\n 'locale: String, fallback: Boolean = true, publicationState: PublicationState = PUBLISHED, snapshot: Int';\n\n/** The definition's GraphQL type and (for models) its root queries and mutations, as SDL. */\nexport const graphqlSdl = (definition: SchemaDefinition, lookup: DefinitionLookup): string => {\n const name = toTypeName(definition.apiKey);\n const system = isModelDefinition(definition)\n ? [\n 'id: ID!',\n 'locale: String!',\n 'createdAt: String!',\n 'updatedAt: String!',\n 'publishedAt: String',\n `localizations: [${name}!]`,\n ]\n : [];\n const fields = liveFields(definition).map(\n (field) => `${field.apiKey}: ${graphqlFieldType(definition, field, lookup)}`,\n );\n const type = `type ${name} {\\n${[...system, ...fields].map((line) => ` ${line}`).join('\\n')}\\n}`;\n if (!isModelDefinition(definition)) {\n return `${type}\\n`;\n }\n const queries =\n definition.kind === 'collection'\n ? [\n `${definition.apiKey}(id: ID!, ${READ_ARGS}): ${name}`,\n `${collectionQueryName(definition)}(filter: ${name}Filter, sort: [${name}Sort!], search: String, page: Int, pageSize: Int, ${READ_ARGS}): ${name}Connection`,\n ]\n : [`${definition.apiKey}(${READ_ARGS}): ${name}`];\n const mutations = MUTATION_PREFIXES.map((prefix) => `${prefix}${name}`);\n return `${type}\\n\\ntype Query {\\n${queries.map((line) => ` ${line}`).join('\\n')}\\n}\\n\\n# Mutations: ${mutations.join(', ')}\\n`;\n};\n"],"file":"shapes-BZ87ap5s.js"}
1
+ {"version":3,"mappings":"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","names":["DEFAULT_SEO_KEYS","isRecord","value","text","resolveSeo","keys","context","output","raw","key","set","next","base","applyTitleTemplate","__iconData","ArrowLeft","createLucideIcon","ChevronsDownUp","RotateCcwClock","__defProp","__name","target","TABS_NAME","createTabsContext","createTabsScope","createContextScope","createRovingFocusGroupScope","useRovingFocusGroupScope","TabsProvider","useTabsContext","Tabs","import_react","__name$2","valueProp","tabsProps","props","direction","useDirection","dir","setValue","useControllableState","onValueChange","defaultValue","import_jsx_runtime","__scopeTabs","useId","Primitive","orientation","forwardedRef","TAB_LIST_NAME","TabsList","listProps","rovingFocusGroupScope","RovingFocusGroup.Root","TRIGGER_NAME","TabsTrigger","triggerProps","triggerId","makeTriggerId","contentId","makeContentId","isSelected","RovingFocusGroup.Item","disabled","composeEventHandlers","event","isAutomaticActivation","CONTENT_NAME","TabsContent","contentProps","isMountAnimationPreventedRef","rAF","Presence","forceMount","present","children","baseId","Root2","List","Trigger","Content","NAME","Toggle","__name$1","pressedProp","buttonProps","pressed","setPressed","onPressedChange","defaultPressed","TOGGLE_GROUP_NAME","createToggleGroupContext","createToggleGroupScope","ToggleGroup","toggleGroupProps","type","ToggleGroupImplSingle","singleProps","ToggleGroupImplMultiple","multipleProps","ToggleGroupValueProvider","useToggleGroupValueContext","toggleGroupSingleProps","ToggleGroupImpl","toggleGroupMultipleProps","handleButtonActivate","prevValue","itemValue","handleButtonDeactivate","value2","ToggleGroupContext","useToggleGroupContext","__scopeToggleGroup","commonProps","rovingFocus","ITEM_NAME","ToggleGroupItem","valueContext","ref","ToggleGroupItemImpl","itemProps","typeProps","TabsPrimitive.Root","cn","className","TabsPrimitive.List","variant","TabsPrimitive.Trigger","TabsPrimitive.Content","EntrySiblings","useFieldsEnvironment","values","useEntryForm","state","siblings","useMemo","model","SiblingValuesContext","FieldsProvider","FieldsEnvironmentContext","environment","EntryFormStoreContext","store","useTopLevelValue","field","useCallback","EditorErrorBoundary","Component","logError","error","info","FieldEditor","useTranslation","control","BuiltInComponent","builtIn","_Fragment","resolved","builtInProps","contractProps","Suspense","Skeleton","FieldMessages","message","PATTERNS","SLUG_PATTERN","UID_PATTERN","DATE_PATTERN","DATETIME_PATTERN","TIME_PATTERN","DECIMAL_PATTERN","BIGINTEGER_PATTERN","issue","code","checkLength","settings","checkRange","checkCount","count","parsesAsJson","checkCode","checkText","pattern","option","clientIssuesOf","isEmptyValue","toList","fieldDomId","prefix","path","toEditorField","toEditorModel","definition","interpolate","name","match","translateKey","i18next","toEditorContext","fallback","pointerOf","segment","issuesByPath","map","issues","countIssuesUnder","list","FORMAT_KEYS","hasFormatKey","setting","describeIssue","t","withCount","settingKey","choicesOf","stringOption","fromChoice","choice","toChoice","isMultiple","CheckboxGroup","selected","choices","horizontal","labelId","describedBy","validation","Checkbox","inputId","readOnly","item","checked","onChange","Label","CheckboxInput","inputAria","HEX_COLOUR","EMPTY_PICKER_VALUE","presetsOf","presets","preset","swatchStyle","colour","ColorInput","textValue","Input","AddItemButton","Button","Plus","label","CHIP_CLASSES","ScopeBadge","localized","Languages","Popover","PopoverTrigger","Globe","PopoverContent","ScopeIcon","Icon","Tooltip","TooltipTrigger","TooltipContent","FieldControl","memo","useFieldControl","LabelElement","inline","layout","topLevel","WIDTH_GRID_CLASSES","WIDTH_CLASSES","widthClassOf","width","fieldGridModeOf","entryLayoutOf","COMPACT_TYPES","isCompact","FieldGrid","mode","fields","renderField","isAssetView","mediaIdOf","collect","liveFields","componentOfItem","components","id","component","COMPONENT_KEY","fromApiValue","convert","withClientKey","toFormValues","data","defaultFormValues","newComponentItem","zoned","toInputValue","stripClientKeys","dirtyKeysOf","isSameContent","baseline","buildPatch","buildCreateData","mergeSaved","current","saved","sent","ComponentItemFields","wrapped","renderFieldFooter","onItemChange","MAX_SUMMARY","truncate","summarizeValue","richTextPlainText","valueLabel","TEXTUAL_TYPES","summarizeItem","titleField","candidates","summary","useCollapsedItems","collapsed","setCollapsed","useState","startCollapsed","initialKeys","useFocusNewItem","previous","useRef","added","domId","DRAG_TYPE","useItemDrag","from","setFrom","over","setOver","reset","index","move","useItemIssueCount","ItemCard","bodyId","onKeyDown","onMove","canvas","appearance","actionClasses","drag","issueCount","editable","title","GripVertical","onToggle","ChevronRight","StatusChip","ArrowUp","ArrowDown","onDuplicate","Copy","onRemove","Trash2","ItemInserter","menu","useDeferredMenuAction","DropdownMenu","DropdownMenuTrigger","DropdownMenuContent","DropdownMenuGroup","DropdownMenuLabel","InsertMenuItem","Boxes","onInsert","Block","itemPath","\"__component\"","itemKey","to","CanvasItemList","Fragment","insertable","newItem","componentOf","toggle","hasRoomFor","max","emptyListMinimum","min","EmptyListRow","minimum","EmptyState","useListEditor","items","commit","clientKeyOf","at","moveItem","copy","RepeatableItem","CanvasRepeatable","room","add","empty","Repeatable","Single","ComponentField","ClearButton","onClear","X","DateInput","pad","length","toDateTimeInput","iso","date","year","month","day","hours","minutes","seconds","utc","fromDateTimeInput","withSeconds","localTimeZone","DateTimeInput","hintId","allowedComponentsOf","useAllowedComponents","AddSectionMenu","allowed","DropdownMenuItem","onAdd","ZoneItem","candidate","CanvasZone","DynamicZoneField","FormZone","allCollapsed","setAll","ChevronsUpDown","ParseError","DEFAULT_ROWS","INDENT","format","parse","JsonEditor","setText","problem","setProblem","seen","setSeen","parsed","isDeepEqual","errorId","Textarea","numberOption","Braces","GalleryTile","asset","useMediaAsset","assetId","Thumbnail","ImageOff","ArrowRight","Gallery","dropping","setDropping","uploading","setUploading","acceptsFiles","canAdd","uploadMedia","onDrop","files","file","toast","ids","onPick","ImagePlus","MediaField","useMediaPermissions","multiple","onBlur","pick","picked","chosen","reportError","AssetTile","canWrite","INTEGER","NUMBER","trimmed","number","NumberInput","invalid","setInvalid","parseErrorId","integer","RadioInput","RadioGroup","RadioGroupItem","MAX_LOOKUP","useEntryLabels","titleFieldOf","lookup","query","locale","useEntryList","TopLevelField","EntryFields","withoutIssuesUnder","apiKey","createEntryFormStore","createStore","initial","local","selectDirtyKeys","contentIssuesOf","ShapioApiError","referrersOf","referrers","isEditConflict","InlineCreateSheet","outer","dirty","useStore","create","useCreateEntry","useDiscardGuard","open","onClose","submit","onCreated","Sheet","requestOpenChange","SheetContent","SheetHeader","SheetTitle","SheetBody","FormError","SheetFooter","SubmitButton","discardPrompt","MD_QUERY","subscribe","getSnapshot","useIsMdUp","useSyncExternalStore","useActiveOption","rememberedId","setActiveId","activeId","delta","PAGE_SIZE","SEARCH_DEBOUNCE_MS","Results","listboxId","q","useDebouncedValue","searchable","isSearchable","exclude","active","optionId","activeDescendant","choose","onUnpick","full","Search","listClassName","Check","labelOf","LoadingState","ErrorState","RelationPicker","isMdUp","titleId","triggerRef","creatingRef","onOpenChange","startCreate","onCloseAutoFocus","creating","trigger","onFocusFallback","onCreate","results","actions","canCreate","SheetTrigger","RelationField","searching","setSearching","setCreating","listRef","labels","canAddMore","labelFor","entryTitle","shortId","IconTile","Layers","toggleVariants","cva","ToggleGroupPrimitive.Root","size","ToggleGroupPrimitive.Item","Segmented","MultiSelect","ChevronDown","DropdownMenuCheckboxItem","SelectInput","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Counter","counter","SOFT_MAX_BY_FIELD_ID","SEO_FIELD_IDS","seoCounterOf","fieldId","BUILT_IN_TYPES","seoComponentDefinition","seoKeysOf","localeChainOf","fallbackLocale","locales","start","chain","entry","seoPreviewOf","localeDefaults","seoDefaultsForLocale","defaults","localeChain","fallbackTitle","useSeoPreview","useSiteSeoDefaults","useLocales","siteName","useMe","titleKey","effectiveTitleField","slugKey","slug","preview","host","urlLine","Preview","headingId","noindex","renderCounter","SeoGroup","noindexKey","SeoField","isSeoField","slugify","useSourceText","useSiblingValues","sourceId","source","SlugInput","sourceText","following","setFollowing","lastSource","Link2","Link2Off","maxLength","countId","TextareaControl","INPUT_TYPES","TextInput","SECONDS_PER_MINUTE","TimeInput","Switch","RichTextField","lazy","module","CodeEditor","BUILT_IN_EDITORS","SEO_EDITOR_ID","builtInEditorFor","compatible","EDITOR_CATALOGUE","DEFAULT_EDITORS","resolveEditor","isCustomEditorId","custom","runtimeEditors","NESTING_TYPES","useFieldMessages","serverIssues","revealed","nesting","server","client","known","touch","messages","descriptionId","errorsId","editorField","editorModel","owner","_definition","_path","_appearance","useEditorManifest","useQuery","queryKeys","adminApi","NO_RUNTIME_EDITORS","editorModuleUrl","apiBaseUrl","importModule","__vitePreload","url","loadRuntimeEditors","editors","problems","manifest","load","definitions","isEditorDefinition","useRuntimeEditors","modules","restEndpoints","isModelDefinition","delivery","routeKeyOf","admin","collection","RICH_TEXT_SAMPLE","MEDIA_SAMPLE","MAX_SAMPLE_DEPTH","sampleValue","many","sampleObject","depth","SYSTEM_SAMPLE","restResponseSample","meta","body","listOf","graphqlFieldType","nameOf","toTypeName","READ_ARGS","graphqlSdl","system","line","queries","collectionQueryName","mutations","MUTATION_PREFIXES"],"ignoreList":[1,2,3,4,5,6],"sources":["../../../../packages/schema/src/seo/resolve.ts","../../../../node_modules/.pnpm/lucide-react@1.49.0_@types+react@19.3.0_react@19.3.0/node_modules/lucide-react/dist/esm/icons/arrow-left.mjs","../../../../node_modules/.pnpm/lucide-react@1.49.0_@types+react@19.3.0_react@19.3.0/node_modules/lucide-react/dist/esm/icons/chevrons-down-up.mjs","../../../../node_modules/.pnpm/lucide-react@1.49.0_@types+react@19.3.0_react@19.3.0/node_modules/lucide-react/dist/esm/icons/rotate-ccw-clock.mjs","../../../../node_modules/.pnpm/@radix-ui+react-tabs@1.1.21_@types+react-dom@19.3.0_@types+react@19.3.0__@types+react@1_c98ff049ac6c06001c8e28faf2978e1a/node_modules/@radix-ui/react-tabs/dist/index.mjs","../../../../node_modules/.pnpm/@radix-ui+react-toggle@1.1.18_@types+react-dom@19.3.0_@types+react@19.3.0__@types+react_3e4dd2eba2183dd95abdddf4ecd4003f/node_modules/@radix-ui/react-toggle/dist/index.mjs","../../../../node_modules/.pnpm/@radix-ui+react-toggle-group@1.1.19_@types+react-dom@19.3.0_@types+react@19.3.0__@types_2e29e58635a712cf598e39122b42ab8c/node_modules/@radix-ui/react-toggle-group/dist/index.mjs","../../src/components/ui/tabs.tsx","../../src/fields/form/EntrySiblings/index.tsx","../../src/fields/form/FieldsProvider/index.tsx","../../src/fields/hooks/useTopLevelValue.ts","../../src/fields/runtime/EditorErrorBoundary/index.tsx","../../src/fields/FieldEditor/index.tsx","../../src/fields/FieldMessages/index.tsx","../../src/fields/helpers/clientValidation.ts","../../src/fields/helpers/domIds.ts","../../src/fields/helpers/editorContext.ts","../../src/fields/helpers/issues.ts","../../src/fields/helpers/choices.ts","../../src/fields/CheckboxGroup/index.tsx","../../src/fields/CheckboxInput/index.tsx","../../src/fields/ColorInput/index.tsx","../../src/fields/AddItemButton/index.tsx","../../src/fields/ScopeBadge/index.tsx","../../src/fields/ScopeIcon/index.tsx","../../src/fields/FieldControl/index.tsx","../../src/fields/helpers/widthClasses.ts","../../src/fields/FieldGrid/index.tsx","../../src/fields/helpers/formValues.ts","../../src/fields/ComponentItemFields/index.tsx","../../src/fields/helpers/summary.ts","../../src/fields/hooks/useCollapsedItems.ts","../../src/fields/hooks/useFocusNewItem.ts","../../src/fields/hooks/useItemDrag.ts","../../src/fields/hooks/useItemIssueCount.ts","../../src/fields/ItemCard/index.tsx","../../src/fields/ItemInserter/index.tsx","../../src/fields/CanvasItemList/index.tsx","../../src/fields/helpers/listLimits.ts","../../src/fields/EmptyListRow/index.tsx","../../src/fields/hooks/useListEditor.ts","../../src/fields/ComponentField/index.tsx","../../src/fields/ClearButton/index.tsx","../../src/fields/DateInput/index.tsx","../../src/fields/helpers/dates.ts","../../src/fields/DateTimeInput/index.tsx","../../src/fields/hooks/useAllowedComponents.ts","../../src/fields/DynamicZoneField/AddSectionMenu/index.tsx","../../src/fields/DynamicZoneField/index.tsx","../../src/fields/ParseError/index.tsx","../../src/fields/JsonEditor/index.tsx","../../src/fields/MediaField/GalleryTile/index.tsx","../../src/fields/MediaField/Gallery/index.tsx","../../src/fields/MediaField/index.tsx","../../src/fields/NumberInput/index.tsx","../../src/fields/RadioInput/index.tsx","../../src/fields/hooks/useEntryLabels.ts","../../src/fields/form/TopLevelField/index.tsx","../../src/fields/form/EntryFields/index.tsx","../../src/fields/form/store.ts","../../src/fields/helpers/apiErrors.ts","../../src/fields/RelationField/InlineCreateSheet/index.tsx","../../src/fields/hooks/useIsMdUp.ts","../../src/fields/RelationField/RelationPicker/hooks/useActiveOption.ts","../../src/fields/RelationField/RelationPicker/Results/index.tsx","../../src/fields/RelationField/RelationPicker/index.tsx","../../src/fields/RelationField/index.tsx","../../src/components/ui/toggle.tsx","../../src/components/ui/toggle-group.tsx","../../src/fields/Segmented/index.tsx","../../src/fields/SelectInput/index.tsx","../../src/fields/SeoField/Counter/index.tsx","../../src/fields/SeoField/helpers.ts","../../src/fields/SeoField/hooks/useSeoPreview.ts","../../src/fields/SeoField/Preview/index.tsx","../../src/fields/SeoField/index.tsx","../../src/fields/helpers/slugify.ts","../../src/fields/SlugInput/index.tsx","../../src/fields/Textarea/index.tsx","../../src/fields/TextInput/index.tsx","../../src/fields/TimeInput/index.tsx","../../src/fields/Toggle/index.tsx","../../src/fields/registry.ts","../../src/fields/hooks/useFieldControl.ts","../../src/api/editors.ts","../../src/fields/runtime/loader.ts","../../src/fields/runtime/useRuntimeEditors.ts","../../src/features/Develop/Schema/helpers/shapes.ts"],"sourcesContent":["import type { SeoLocaleDefaults } from './defaults.js';\nimport type { SeoFieldKey } from './ids.js';\nimport { applyTitleTemplate } from './locale.js';\n\n/** The API IDs under which a delivered SEO value carries each built-in field (absent: removed or retyped). */\nexport type SeoKeys = Partial<Record<SeoFieldKey, string>>;\n\n/** The API IDs the built-in component is created with. */\nexport const DEFAULT_SEO_KEYS: Required<SeoKeys> = {\n title: 'title',\n description: 'description',\n image: 'image',\n canonical: 'canonical',\n noindex: 'noindex',\n};\n\nexport type ResolveSeoContext = {\n /** The site's default texts for the entry's locale (`seoDefaultsForLocale`). */\n defaults: SeoLocaleDefaults;\n /** The default social image in the delivered asset shape, or null. */\n image: unknown;\n /** The entry's own title (its title field) when the SEO title is empty; null when none is readable. */\n fallbackTitle: string | null;\n /** Where each field sits in `raw`; defaults to the built-in API IDs. */\n keys?: SeoKeys;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst text = (value: unknown): string | null =>\n typeof value === 'string' && value.trim() !== '' ? value : null;\n\n/**\n * The effective SEO values of one delivered entry, in the same shape as the raw value (plan seo-fields): the\n * title is the entry's SEO title, else its own title, through the site's template (the bare site name when\n * neither exists, never templated); description and image fall back to the site's defaults; canonical stays\n * the entry's value or null; noindex is a boolean. Other keys (fields a user added) pass through. Pure.\n */\nexport const resolveSeo = (raw: unknown, context: ResolveSeoContext): Record<string, unknown> => {\n const keys = context.keys ?? DEFAULT_SEO_KEYS;\n const output: Record<string, unknown> = isRecord(raw) ? { ...raw } : {};\n const value = (key: SeoFieldKey) => (keys[key] === undefined ? undefined : output[keys[key]]);\n const set = (key: SeoFieldKey, next: unknown) => {\n if (keys[key] !== undefined) {\n output[keys[key]] = next;\n }\n };\n const base = text(value('title')) ?? text(context.fallbackTitle);\n set(\n 'title',\n base !== null\n ? applyTitleTemplate(base, context.defaults.titleTemplate)\n : (context.defaults.siteName ?? null),\n );\n set('description', text(value('description')) ?? context.defaults.description ?? null);\n set('image', value('image') ?? context.image ?? null);\n set('canonical', text(value('canonical')));\n set('noindex', value('noindex') === true);\n return output;\n};\n","/**\n * @license lucide-react v1.49.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"arrow-left\",\n size: 24,\n node: [\n [\"path\", { d: \"m12 19-7-7 7-7\", key: \"1l729n\" }],\n [\"path\", { d: \"M19 12H5\", key: \"x3x0zl\" }]\n ]\n};\n__iconData.node;\nconst ArrowLeft = createLucideIcon(__iconData);\n\nexport { __iconData, ArrowLeft as default };\n//# sourceMappingURL=arrow-left.mjs.map\n","/**\n * @license lucide-react v1.49.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"chevrons-down-up\",\n size: 24,\n node: [\n [\"path\", { d: \"m7 20 5-5 5 5\", key: \"13a0gw\" }],\n [\"path\", { d: \"m7 4 5 5 5-5\", key: \"1kwcof\" }]\n ]\n};\n__iconData.node;\nconst ChevronsDownUp = createLucideIcon(__iconData);\n\nexport { __iconData, ChevronsDownUp as default };\n//# sourceMappingURL=chevrons-down-up.mjs.map\n","/**\n * @license lucide-react v1.49.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"rotate-ccw-clock\",\n size: 24,\n node: [\n [\"path\", { d: \"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"1357e3\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }],\n [\"path\", { d: \"M12 7v5l4 2\", key: \"1fdv2h\" }]\n ],\n aliases: [\"history\"]\n};\n__iconData.node;\nconst RotateCcwClock = createLucideIcon(__iconData);\n\nexport { __iconData, RotateCcwClock as default };\n//# sourceMappingURL=rotate-ccw-clock.mjs.map\n","\"use client\";\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\n// src/tabs.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { createRovingFocusGroupScope } from \"@radix-ui/react-roving-focus\";\nimport { Presence } from \"@radix-ui/react-presence\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as RovingFocusGroup from \"@radix-ui/react-roving-focus\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { jsx } from \"react/jsx-runtime\";\nvar TABS_NAME = \"Tabs\";\nvar [createTabsContext, createTabsScope] = createContextScope(TABS_NAME, [\n createRovingFocusGroupScope\n]);\nvar useRovingFocusGroupScope = createRovingFocusGroupScope();\nvar [TabsProvider, useTabsContext] = createTabsContext(TABS_NAME);\nvar Tabs = /* @__PURE__ */ React.forwardRef(\n // blank line to reduce diff noise\n /* @__PURE__ */ __name(function Tabs2(props, forwardedRef) {\n const {\n __scopeTabs,\n value: valueProp,\n onValueChange,\n defaultValue,\n orientation = \"horizontal\",\n dir,\n activationMode = \"automatic\",\n ...tabsProps\n } = props;\n const direction = useDirection(dir);\n const [value, setValue] = useControllableState({\n prop: valueProp,\n onChange: onValueChange,\n defaultProp: defaultValue ?? \"\",\n caller: TABS_NAME\n });\n return /* @__PURE__ */ jsx(\n TabsProvider,\n {\n scope: __scopeTabs,\n baseId: useId(),\n value,\n onValueChange: setValue,\n orientation,\n dir: direction,\n activationMode,\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n dir: direction,\n \"data-orientation\": orientation,\n ...tabsProps,\n ref: forwardedRef\n }\n )\n }\n );\n }, \"Tabs\")\n);\nvar TAB_LIST_NAME = \"TabsList\";\nvar TabsList = /* @__PURE__ */ React.forwardRef(\n // blank line to reduce diff noise\n /* @__PURE__ */ __name(function TabsList2(props, forwardedRef) {\n const { __scopeTabs, loop = true, ...listProps } = props;\n const context = useTabsContext(TAB_LIST_NAME, __scopeTabs);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);\n return /* @__PURE__ */ jsx(\n RovingFocusGroup.Root,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n orientation: context.orientation,\n dir: context.dir,\n loop,\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n role: \"tablist\",\n \"aria-orientation\": context.orientation,\n ...listProps,\n ref: forwardedRef\n }\n )\n }\n );\n }, \"TabsList\")\n);\nvar TRIGGER_NAME = \"TabsTrigger\";\nvar TabsTrigger = /* @__PURE__ */ React.forwardRef(\n /* @__PURE__ */ __name(function TabsTrigger2(props, forwardedRef) {\n const { __scopeTabs, value, disabled = false, ...triggerProps } = props;\n const context = useTabsContext(TRIGGER_NAME, __scopeTabs);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);\n const triggerId = makeTriggerId(context.baseId, value);\n const contentId = makeContentId(context.baseId, value);\n const isSelected = value === context.value;\n return /* @__PURE__ */ jsx(\n RovingFocusGroup.Item,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n focusable: !disabled,\n active: isSelected,\n children: /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n role: \"tab\",\n \"aria-selected\": isSelected,\n \"aria-controls\": contentId,\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n \"data-disabled\": disabled ? \"\" : void 0,\n disabled,\n id: triggerId,\n ...triggerProps,\n ref: forwardedRef,\n onMouseDown: composeEventHandlers(props.onMouseDown, (event) => {\n if (!disabled && event.button === 0 && event.ctrlKey === false) {\n context.onValueChange(value);\n } else {\n event.preventDefault();\n }\n }),\n onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {\n if (disabled || event.target !== event.currentTarget) {\n return;\n }\n if ([\" \", \"Enter\"].includes(event.key)) {\n context.onValueChange(value);\n }\n }),\n onFocus: composeEventHandlers(props.onFocus, () => {\n const isAutomaticActivation = context.activationMode !== \"manual\";\n if (!isSelected && !disabled && isAutomaticActivation) {\n context.onValueChange(value);\n }\n })\n }\n )\n }\n );\n }, \"TabsTrigger\")\n);\nvar CONTENT_NAME = \"TabsContent\";\nvar TabsContent = /* @__PURE__ */ React.forwardRef(\n /* @__PURE__ */ __name(function TabsContent2(props, forwardedRef) {\n const { __scopeTabs, value, forceMount, children, ...contentProps } = props;\n const context = useTabsContext(CONTENT_NAME, __scopeTabs);\n const triggerId = makeTriggerId(context.baseId, value);\n const contentId = makeContentId(context.baseId, value);\n const isSelected = value === context.value;\n const isMountAnimationPreventedRef = React.useRef(isSelected);\n React.useEffect(() => {\n const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);\n return () => cancelAnimationFrame(rAF);\n }, []);\n return /* @__PURE__ */ jsx(Presence, { present: forceMount || isSelected, children: ({ present }) => /* @__PURE__ */ jsx(\n Primitive.div,\n {\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n \"data-orientation\": context.orientation,\n role: \"tabpanel\",\n \"aria-labelledby\": triggerId,\n hidden: !present,\n id: contentId,\n tabIndex: 0,\n ...contentProps,\n ref: forwardedRef,\n style: {\n ...props.style,\n animationDuration: isMountAnimationPreventedRef.current ? \"0s\" : void 0\n },\n children: present && children\n }\n ) });\n }, \"TabsContent\")\n);\nfunction makeTriggerId(baseId, value) {\n return `${baseId}-trigger-${value}`;\n}\n__name(makeTriggerId, \"makeTriggerId\");\nfunction makeContentId(baseId, value) {\n return `${baseId}-content-${value}`;\n}\n__name(makeContentId, \"makeContentId\");\nvar Root2 = Tabs;\nvar List = TabsList;\nvar Trigger = TabsTrigger;\nvar Content = TabsContent;\nexport {\n Content,\n List,\n Root2 as Root,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Trigger,\n createTabsScope\n};\n//# sourceMappingURL=index.mjs.map\n","\"use client\";\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\n// src/toggle.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { jsx } from \"react/jsx-runtime\";\nvar NAME = \"Toggle\";\nvar Toggle = /* @__PURE__ */ React.forwardRef(\n /* @__PURE__ */ __name(function Toggle2(props, forwardedRef) {\n const { pressed: pressedProp, defaultPressed, onPressedChange, ...buttonProps } = props;\n const [pressed, setPressed] = useControllableState({\n prop: pressedProp,\n onChange: onPressedChange,\n defaultProp: defaultPressed ?? false,\n caller: NAME\n });\n return /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n \"aria-pressed\": pressed,\n \"data-state\": pressed ? \"on\" : \"off\",\n \"data-disabled\": props.disabled ? \"\" : void 0,\n ...buttonProps,\n ref: forwardedRef,\n onClick: composeEventHandlers(props.onClick, () => {\n if (!props.disabled) {\n setPressed(!pressed);\n }\n })\n }\n );\n }, \"Toggle\")\n);\nvar Root = Toggle;\nexport {\n Root,\n Toggle\n};\n//# sourceMappingURL=index.mjs.map\n","\"use client\";\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\n// src/toggle-group.tsx\nimport * as React from \"react\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as RovingFocusGroup from \"@radix-ui/react-roving-focus\";\nimport { createRovingFocusGroupScope } from \"@radix-ui/react-roving-focus\";\nimport { Toggle } from \"@radix-ui/react-toggle\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { jsx } from \"react/jsx-runtime\";\nvar TOGGLE_GROUP_NAME = \"ToggleGroup\";\nvar [createToggleGroupContext, createToggleGroupScope] = createContextScope(TOGGLE_GROUP_NAME, [\n createRovingFocusGroupScope\n]);\nvar useRovingFocusGroupScope = createRovingFocusGroupScope();\nvar ToggleGroup = /* @__PURE__ */ React.forwardRef(/* @__PURE__ */ __name(function ToggleGroup2(props, forwardedRef) {\n const { type, ...toggleGroupProps } = props;\n if (type === \"single\") {\n const singleProps = toggleGroupProps;\n return /* @__PURE__ */ jsx(ToggleGroupImplSingle, { role: \"radiogroup\", ...singleProps, ref: forwardedRef });\n }\n if (type === \"multiple\") {\n const multipleProps = toggleGroupProps;\n return /* @__PURE__ */ jsx(ToggleGroupImplMultiple, { role: \"toolbar\", ...multipleProps, ref: forwardedRef });\n }\n throw new Error(`Missing prop \\`type\\` expected on \\`${TOGGLE_GROUP_NAME}\\``);\n}, \"ToggleGroup\"));\nvar [ToggleGroupValueProvider, useToggleGroupValueContext] = createToggleGroupContext(TOGGLE_GROUP_NAME);\nvar ToggleGroupImplSingle = /* @__PURE__ */ React.forwardRef(/* @__PURE__ */ __name(function ToggleGroupImplSingle2(props, forwardedRef) {\n const {\n value: valueProp,\n defaultValue,\n onValueChange = /* @__PURE__ */ __name(() => {\n }, \"onValueChange\"),\n ...toggleGroupSingleProps\n } = props;\n const [value, setValue] = useControllableState({\n prop: valueProp,\n defaultProp: defaultValue ?? \"\",\n onChange: onValueChange,\n caller: TOGGLE_GROUP_NAME\n });\n return /* @__PURE__ */ jsx(\n ToggleGroupValueProvider,\n {\n scope: props.__scopeToggleGroup,\n type: \"single\",\n value: React.useMemo(() => value ? [value] : [], [value]),\n onItemActivate: setValue,\n onItemDeactivate: React.useCallback(() => setValue(\"\"), [setValue]),\n children: /* @__PURE__ */ jsx(ToggleGroupImpl, { ...toggleGroupSingleProps, ref: forwardedRef })\n }\n );\n}, \"ToggleGroupImplSingle\"));\nvar ToggleGroupImplMultiple = /* @__PURE__ */ React.forwardRef(/* @__PURE__ */ __name(function ToggleGroupImplMultiple2(props, forwardedRef) {\n const {\n value: valueProp,\n defaultValue,\n onValueChange = /* @__PURE__ */ __name(() => {\n }, \"onValueChange\"),\n ...toggleGroupMultipleProps\n } = props;\n const [value, setValue] = useControllableState({\n prop: valueProp,\n defaultProp: defaultValue ?? [],\n onChange: onValueChange,\n caller: TOGGLE_GROUP_NAME\n });\n const handleButtonActivate = React.useCallback(\n (itemValue) => setValue((prevValue = []) => [...prevValue, itemValue]),\n [setValue]\n );\n const handleButtonDeactivate = React.useCallback(\n (itemValue) => setValue((prevValue = []) => prevValue.filter((value2) => value2 !== itemValue)),\n [setValue]\n );\n return /* @__PURE__ */ jsx(\n ToggleGroupValueProvider,\n {\n scope: props.__scopeToggleGroup,\n type: \"multiple\",\n value,\n onItemActivate: handleButtonActivate,\n onItemDeactivate: handleButtonDeactivate,\n children: /* @__PURE__ */ jsx(ToggleGroupImpl, { ...toggleGroupMultipleProps, ref: forwardedRef })\n }\n );\n}, \"ToggleGroupImplMultiple\"));\nvar [ToggleGroupContext, useToggleGroupContext] = createToggleGroupContext(TOGGLE_GROUP_NAME);\nvar ToggleGroupImpl = /* @__PURE__ */ React.forwardRef(\n // blank line to reduce diff noise\n /* @__PURE__ */ __name(function ToggleGroupImpl2(props, forwardedRef) {\n const {\n __scopeToggleGroup,\n disabled = false,\n rovingFocus = true,\n orientation,\n dir,\n loop = true,\n ...toggleGroupProps\n } = props;\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeToggleGroup);\n const direction = useDirection(dir);\n const commonProps = { dir: direction, ...toggleGroupProps };\n return /* @__PURE__ */ jsx(ToggleGroupContext, { scope: __scopeToggleGroup, rovingFocus, disabled, children: rovingFocus ? /* @__PURE__ */ jsx(\n RovingFocusGroup.Root,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n orientation,\n dir: direction,\n loop,\n children: /* @__PURE__ */ jsx(Primitive.div, { ...commonProps, ref: forwardedRef })\n }\n ) : /* @__PURE__ */ jsx(Primitive.div, { ...commonProps, ref: forwardedRef }) });\n }, \"ToggleGroupImpl\")\n);\nvar ITEM_NAME = \"ToggleGroupItem\";\nvar ToggleGroupItem = /* @__PURE__ */ React.forwardRef(\n // blank line to reduce diff noise\n /* @__PURE__ */ __name(function ToggleGroupItem2(props, forwardedRef) {\n const valueContext = useToggleGroupValueContext(ITEM_NAME, props.__scopeToggleGroup);\n const context = useToggleGroupContext(ITEM_NAME, props.__scopeToggleGroup);\n const rovingFocusGroupScope = useRovingFocusGroupScope(props.__scopeToggleGroup);\n const pressed = valueContext.value.includes(props.value);\n const disabled = context.disabled || props.disabled;\n const commonProps = { ...props, pressed, disabled };\n const ref = React.useRef(null);\n return context.rovingFocus ? /* @__PURE__ */ jsx(\n RovingFocusGroup.Item,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n focusable: !disabled,\n active: pressed,\n ref,\n children: /* @__PURE__ */ jsx(ToggleGroupItemImpl, { ...commonProps, ref: forwardedRef })\n }\n ) : /* @__PURE__ */ jsx(ToggleGroupItemImpl, { ...commonProps, ref: forwardedRef });\n }, \"ToggleGroupItem\")\n);\nvar ToggleGroupItemImpl = /* @__PURE__ */ React.forwardRef(\n // blank line to reduce diff noise\n /* @__PURE__ */ __name(function ToggleGroupItemImpl2(props, forwardedRef) {\n const { __scopeToggleGroup, value, ...itemProps } = props;\n const valueContext = useToggleGroupValueContext(ITEM_NAME, __scopeToggleGroup);\n const singleProps = { role: \"radio\", \"aria-checked\": props.pressed, \"aria-pressed\": void 0 };\n const typeProps = valueContext.type === \"single\" ? singleProps : void 0;\n return /* @__PURE__ */ jsx(\n Toggle,\n {\n ...typeProps,\n ...itemProps,\n ref: forwardedRef,\n onPressedChange: (pressed) => {\n if (pressed) {\n valueContext.onItemActivate(value);\n } else {\n valueContext.onItemDeactivate(value);\n }\n }\n }\n );\n }, \"ToggleGroupItemImpl\")\n);\nexport {\n ToggleGroupItem as Item,\n ToggleGroup as Root,\n ToggleGroup,\n ToggleGroupItem,\n createToggleGroupScope\n};\n//# sourceMappingURL=index.mjs.map\n","import { Tabs as TabsPrimitive } from 'radix-ui';\nimport * as React from 'react';\nimport { cn } from '@/helpers/cn';\n\nfunction Tabs({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {\n return <TabsPrimitive.Root data-slot=\"tabs\" className={cn('flex flex-col gap-2', className)} {...props} />;\n}\n\n// Shapio: `underline` is the page-level style (2px primary bar under the active tab, DESIGN.md); `default`\n// is the segmented control for small in-panel switches.\nfunction TabsList({\n className,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.List> & { variant?: 'default' | 'underline' }) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n data-variant={variant}\n className={cn(\n 'group/tabs-list inline-flex w-fit items-center text-muted-foreground',\n variant === 'default' && 'h-9 justify-center rounded-lg bg-muted p-[3px]',\n variant === 'underline' && 'h-10 w-full justify-start gap-5 border-b',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"inline-flex items-center justify-center gap-1.5 text-sm whitespace-nowrap transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n // Segmented\n 'group-data-[variant=default]/tabs-list:h-[calc(100%-1px)] group-data-[variant=default]/tabs-list:flex-1 group-data-[variant=default]/tabs-list:rounded-md group-data-[variant=default]/tabs-list:border group-data-[variant=default]/tabs-list:border-transparent group-data-[variant=default]/tabs-list:px-2 group-data-[variant=default]/tabs-list:py-1 group-data-[variant=default]/tabs-list:font-medium group-data-[variant=default]/tabs-list:text-foreground group-data-[variant=default]/tabs-list:data-[state=active]:bg-background group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm dark:group-data-[variant=default]/tabs-list:text-muted-foreground dark:group-data-[variant=default]/tabs-list:data-[state=active]:border-input dark:group-data-[variant=default]/tabs-list:data-[state=active]:bg-input/30 dark:group-data-[variant=default]/tabs-list:data-[state=active]:text-foreground',\n // Underline\n 'group-data-[variant=underline]/tabs-list:relative group-data-[variant=underline]/tabs-list:h-full group-data-[variant=underline]/tabs-list:rounded-sm group-data-[variant=underline]/tabs-list:px-0.5 group-data-[variant=underline]/tabs-list:font-semibold group-data-[variant=underline]/tabs-list:after:absolute group-data-[variant=underline]/tabs-list:after:inset-x-0 group-data-[variant=underline]/tabs-list:after:-bottom-px group-data-[variant=underline]/tabs-list:after:h-0.5 group-data-[variant=underline]/tabs-list:after:rounded-full group-data-[variant=underline]/tabs-list:hover:text-foreground group-data-[variant=underline]/tabs-list:data-[state=active]:text-foreground group-data-[variant=underline]/tabs-list:data-[state=active]:after:bg-primary',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return (\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n // Shapio: the panel is a Tab stop (Radix), so it shows the same focus ring as every other control.\n className={cn(\n 'flex-1 rounded-md outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent };\n","import type { ReactNode } from 'react';\nimport { useMemo } from 'react';\nimport { SiblingValuesContext, useEntryForm, useFieldsEnvironment } from '../context';\n\ntype EntrySiblingsProps = { children: ReactNode };\n\n/** Gives slug fields their source field's value; only its consumers re-render as values change. */\nexport const EntrySiblings = ({ children }: EntrySiblingsProps) => {\n const { model } = useFieldsEnvironment();\n const values = useEntryForm((state) => state.values);\n const siblings = useMemo(() => ({ definition: model, values }), [model, values]);\n return <SiblingValuesContext.Provider value={siblings}>{children}</SiblingValuesContext.Provider>;\n};\n","import type { ReactNode } from 'react';\nimport { EntryFormStoreContext, FieldsEnvironmentContext, type FieldsEnvironment } from '../context';\nimport type { EntryFormStore } from '../store';\n\ntype FieldsProviderProps = { environment: FieldsEnvironment; store: EntryFormStore; children: ReactNode };\n\nexport const FieldsProvider = ({ environment, store, children }: FieldsProviderProps) => (\n <FieldsEnvironmentContext.Provider value={environment}>\n <EntryFormStoreContext.Provider value={store}>{children}</EntryFormStoreContext.Provider>\n </FieldsEnvironmentContext.Provider>\n);\n","import type { FieldDefinition } from '@shapio/schema';\nimport { useCallback } from 'react';\nimport { useEntryForm } from '../form/context';\n\n/** One top-level field's value and setter: subscribes to that value only, so typing re-renders one field. */\nexport const useTopLevelValue = (field: FieldDefinition) => {\n const value = useEntryForm((state) => state.values[field.apiKey]);\n const setValue = useEntryForm((state) => state.setValue);\n const onChange = useCallback((next: unknown) => setValue(field.apiKey, next), [setValue, field.apiKey]);\n return { value, onChange };\n};\n","import { Component, type ErrorInfo, type ReactNode } from 'react';\nimport { logError } from '@/helpers/reportError';\n\ntype EditorErrorBoundaryProps = {\n editorId: string;\n /** Rendered instead of the editor once it has thrown. */\n fallback: ReactNode;\n children: ReactNode;\n};\n\ntype EditorErrorBoundaryState = { failed: boolean };\n\n/**\n * Keeps a crashing custom editor from taking the whole form down: the field falls back to its built-in\n * editor. React only offers error boundaries as class components, so this is the one class in the admin.\n */\nexport class EditorErrorBoundary extends Component<EditorErrorBoundaryProps, EditorErrorBoundaryState> {\n override state: EditorErrorBoundaryState = { failed: false };\n\n static getDerivedStateFromError(): EditorErrorBoundaryState {\n return { failed: true };\n }\n\n override componentDidCatch(error: unknown, info: ErrorInfo) {\n logError(error, `custom editor ${this.props.editorId} crashed${info.componentStack ?? ''}`);\n }\n\n override render() {\n return this.state.failed ? this.props.fallback : this.props.children;\n }\n}\n","import { Suspense } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Skeleton } from '@/components/ui/skeleton';\nimport type { FieldControlState } from '../hooks/useFieldControl';\nimport { EditorErrorBoundary } from '../runtime/EditorErrorBoundary';\n\ntype FieldEditorProps = { control: FieldControlState };\n\n/**\n * The editor a field resolves to: a project's custom editor (falling back to the built-in if it throws) or\n * a built-in one (lazy ones show a skeleton while they load), plus the note when a custom editor is missing.\n */\nexport const FieldEditor = ({ control }: FieldEditorProps) => {\n const { t } = useTranslation();\n const { resolved, builtIn, builtInProps, contractProps } = control;\n const BuiltInComponent = builtIn.component;\n return (\n <>\n {resolved.kind === 'runtime' ? (\n <EditorErrorBoundary\n editorId={resolved.definition.id}\n fallback={<BuiltInComponent {...builtInProps} />}\n >\n <resolved.definition.component {...contractProps} />\n </EditorErrorBoundary>\n ) : (\n <Suspense fallback={<Skeleton className=\"h-24 w-full\" />}>\n <BuiltInComponent {...builtInProps} />\n </Suspense>\n )}\n {resolved.kind === 'builtIn' && resolved.missingCustomId ? (\n <p className=\"text-meta text-muted-foreground\">\n {t('content.fields.customEditorMissing', { id: resolved.missingCustomId })}\n </p>\n ) : null}\n </>\n );\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport type { FieldControlState } from '../hooks/useFieldControl';\n\ntype FieldMessagesProps = { field: FieldDefinition; control: FieldControlState };\n\n/** A field's description (written by the model's author, always visible) and its inline errors. */\nexport const FieldMessages = ({ field, control }: FieldMessagesProps) => (\n <>\n {field.description ? (\n <p id={control.descriptionId} className=\"text-meta text-muted-foreground\">\n {field.description}\n </p>\n ) : null}\n {control.messages.length > 0 ? (\n <ul id={control.errorsId} className=\"space-y-0.5 text-meta font-medium text-destructive\">\n {control.messages.map((message) => (\n <li key={message}>{message}</li>\n ))}\n </ul>\n ) : null}\n </>\n);\n","import type { ContentIssue } from '@shapio/client';\nimport {\n BIGINTEGER_PATTERN,\n DATE_PATTERN,\n DATETIME_PATTERN,\n DECIMAL_PATTERN,\n SLUG_PATTERN,\n TIME_PATTERN,\n UID_PATTERN,\n type FieldDefinition,\n} from '@shapio/schema';\nimport { isEmptyValue, toList } from './values';\n\n/**\n * Checks the admin runs while someone types, so obvious mistakes show before saving. The server is the\n * enforcement layer (CONTRIBUTING.md rule 5) and runs the full validator on every save; these only mirror the\n * cheap, local rules (format, length, range, counts). `required` is left to the server, which skips it on\n * autosave by design.\n */\ntype ClientIssue = Pick<ContentIssue, 'code' | 'message'>;\n\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nconst URL_PATTERN = /^(https?:\\/\\/[^\\s]+|mailto:[^\\s]+|tel:[^\\s]+)$/i;\n\nconst PATTERNS: Partial<Record<FieldDefinition['type'], RegExp>> = {\n email: EMAIL_PATTERN,\n url: URL_PATTERN,\n slug: SLUG_PATTERN,\n uid: UID_PATTERN,\n date: DATE_PATTERN,\n datetime: DATETIME_PATTERN,\n time: TIME_PATTERN,\n decimal: DECIMAL_PATTERN,\n biginteger: BIGINTEGER_PATTERN,\n};\n\nconst issue = (code: string): ClientIssue => ({ code, message: code });\n\nconst checkLength = (text: string, settings: { minLength?: number; maxLength?: number }): ClientIssue[] => [\n ...(settings.minLength !== undefined && text.length < settings.minLength ? [issue('TOO_SHORT')] : []),\n ...(settings.maxLength !== undefined && text.length > settings.maxLength ? [issue('TOO_LONG')] : []),\n];\n\nconst checkRange = (value: number, settings: { min?: number | string; max?: number | string }) => [\n ...(settings.min !== undefined && value < Number(settings.min) ? [issue('TOO_SMALL')] : []),\n ...(settings.max !== undefined && value > Number(settings.max) ? [issue('TOO_LARGE')] : []),\n];\n\nconst checkCount = (count: number, settings: { min?: number; max?: number }) => [\n ...(settings.min !== undefined && count > 0 && count < settings.min ? [issue('TOO_FEW')] : []),\n ...(settings.max !== undefined && count > settings.max ? [issue('TOO_MANY')] : []),\n];\n\nconst parsesAsJson = (text: string) => {\n try {\n JSON.parse(text);\n return true;\n } catch {\n return false;\n }\n};\n\n/** Code is never changed or trimmed; with `validate` on (JSON only) it must parse. */\nconst checkCode = (text: string, settings: { language: string; validate?: boolean | undefined }) =>\n settings.validate === true && settings.language === 'json' && !parsesAsJson(text)\n ? [issue('INVALID_FORMAT')]\n : [];\n\nconst checkText = (field: FieldDefinition, text: string): ClientIssue[] => {\n const pattern = PATTERNS[field.type];\n if (pattern && !pattern.test(text)) {\n return [issue('INVALID_FORMAT')];\n }\n switch (field.type) {\n case 'string':\n case 'text':\n case 'slug':\n case 'uid':\n return checkLength(text, field.settings);\n case 'code':\n return [...checkCode(text, field.settings), ...checkLength(text, field.settings)];\n case 'decimal':\n case 'biginteger':\n return checkRange(Number(text), field.settings);\n case 'enum':\n return field.settings.values.some((option) => option.value === text) ? [] : [issue('NOT_ALLOWED')];\n default:\n return [];\n }\n};\n\nexport const clientIssuesOf = (field: FieldDefinition, value: unknown): ClientIssue[] => {\n if (isEmptyValue(value)) {\n return [];\n }\n switch (field.type) {\n case 'number':\n case 'integer':\n if (typeof value !== 'number' || Number.isNaN(value)) {\n return [issue('INVALID_TYPE')];\n }\n return field.type === 'integer' && !Number.isInteger(value)\n ? [issue('INVALID_TYPE')]\n : checkRange(value, field.settings);\n case 'media':\n case 'relation':\n case 'component':\n case 'dynamiczone':\n return checkCount(toList(value).length, field.settings);\n default:\n return typeof value === 'string' ? checkText(field, value) : [];\n }\n};\n","/** The DOM id of a field's control: unique per form (`prefix`) and value path (`/hero/title`). */\nexport const fieldDomId = (prefix: string, path: string) =>\n `${prefix}field${path.replace(/[^A-Za-z0-9_-]/g, '-')}`;\n","import type { EditorContext, EditorField, EditorModel } from '@shapio/editor-sdk';\nimport type { FieldDefinition, SchemaDefinition } from '@shapio/schema';\nimport { i18next } from '@/app/i18n';\nimport type { FieldsEnvironment } from '../form/context';\n\n/** The editor contract's view of a field: metadata only, nothing an editor could use to reach the backend. */\nexport const toEditorField = (field: FieldDefinition): EditorField => ({\n id: field.id,\n apiKey: field.apiKey,\n label: field.label,\n description: field.description,\n type: field.type,\n required: field.required,\n localized: field.localized,\n settings: field.settings,\n options: field.editor.options,\n});\n\nexport const toEditorModel = (definition: SchemaDefinition): EditorModel => ({\n id: definition.id,\n apiKey: definition.apiKey,\n label: definition.label,\n kind: definition.kind,\n localized: definition.kind === 'component' ? false : definition.localized,\n});\n\nconst interpolate = (text: string, values: Readonly<Record<string, string | number>> | undefined) =>\n values\n ? text.replace(/\\{\\{\\s*(\\w+)\\s*\\}\\}/g, (match, name: string) => String(values[name] ?? match))\n : text;\n\n/** Custom editors ask for keys by name at runtime, so this lookup is untyped by design. */\nconst translateKey = i18next.t.bind(i18next) as unknown as (\n key: string,\n values?: Readonly<Record<string, string | number>>,\n) => string;\n\n/** The limited capabilities an editor gets (ADR 0009): locale, entry, media picking, translation. */\nexport const toEditorContext = (environment: FieldsEnvironment): EditorContext => ({\n locale: environment.locale,\n entryId: environment.entryId,\n uiLanguage: i18next.language,\n pickMedia: environment.pickMedia,\n translate: (key, fallback, values) =>\n i18next.exists(key) ? translateKey(key, values) : interpolate(fallback, values),\n});\n","import type { ContentIssue } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { i18next } from '@/app/i18n';\n\n/**\n * Validation issues (the server's 422 CONTENT_INVALID `details.issues`, and the admin's own client-side\n * checks) keyed by JSON pointer in API keys, e.g. `/sections/0/title`, the same paths the form uses.\n */\nexport type IssueMap = ReadonlyMap<string, readonly ContentIssue[]>;\n\n/** RFC 6901 pointer segment. API keys never need escaping, but component keys and indexes are appended. */\nexport const pointerOf = (base: string, segment: string | number) =>\n `${base}/${String(segment).replace(/~/g, '~0').replace(/\\//g, '~1')}`;\n\nexport const issuesByPath = (issues: readonly ContentIssue[]): IssueMap => {\n const map = new Map<string, ContentIssue[]>();\n for (const issue of issues) {\n map.set(issue.path, [...(map.get(issue.path) ?? []), issue]);\n }\n return map;\n};\n\n/** How many issues sit at or below a path (shown on collapsed items and section links). */\nexport const countIssuesUnder = (issues: IssueMap, path: string): number => {\n let count = 0;\n for (const [key, list] of issues) {\n if (key === path || key.startsWith(`${path}/`)) {\n count += list.length;\n }\n }\n return count;\n};\n\nconst FORMAT_KEYS = {\n email: 'content.issues.format.email',\n url: 'content.issues.format.url',\n slug: 'content.issues.format.slug',\n uid: 'content.issues.format.uid',\n date: 'content.issues.format.date',\n datetime: 'content.issues.format.datetime',\n time: 'content.issues.format.time',\n decimal: 'content.issues.format.decimal',\n biginteger: 'content.issues.format.biginteger',\n code: 'content.issues.format.code',\n} as const;\n\ntype CountKey =\n | 'content.issues.tooShort'\n | 'content.issues.tooLong'\n | 'content.issues.tooSmall'\n | 'content.issues.tooLarge'\n | 'content.issues.tooFew'\n | 'content.issues.tooMany';\n\nconst hasFormatKey = (type: string): type is keyof typeof FORMAT_KEYS => Object.hasOwn(FORMAT_KEYS, type);\n\nconst setting = (field: FieldDefinition | undefined, key: string): string | number | undefined => {\n const value = (field?.settings as Record<string, unknown> | undefined)?.[key];\n return typeof value === 'number' || typeof value === 'string' ? value : undefined;\n};\n\n/** A translated message for an issue. Without the numbers a message needs, the server's text is used. */\nexport const describeIssue = (\n issue: Pick<ContentIssue, 'code' | 'message'>,\n field?: FieldDefinition,\n): string => {\n const t = i18next.t.bind(i18next);\n const withCount = (key: CountKey, settingKey: string) => {\n const count = setting(field, settingKey);\n return count === undefined ? issue.message : t(key, { count: Number(count), value: String(count) });\n };\n switch (issue.code) {\n case 'REQUIRED':\n return t('content.issues.required');\n case 'INVALID_TYPE':\n return t('content.issues.invalidType');\n case 'INVALID_FORMAT':\n return field && hasFormatKey(field.type)\n ? t(FORMAT_KEYS[field.type])\n : t('content.issues.invalidFormat');\n case 'TOO_SHORT':\n return withCount('content.issues.tooShort', 'minLength');\n case 'TOO_LONG':\n return withCount('content.issues.tooLong', 'maxLength');\n case 'TOO_SMALL':\n return withCount('content.issues.tooSmall', 'min');\n case 'TOO_LARGE':\n return withCount('content.issues.tooLarge', 'max');\n case 'TOO_FEW':\n return withCount('content.issues.tooFew', 'min');\n case 'TOO_MANY':\n return withCount('content.issues.tooMany', 'max');\n case 'NOT_ALLOWED':\n return t('content.issues.notAllowed');\n case 'PATTERN_MISMATCH':\n return t('content.issues.patternMismatch');\n case 'DUPLICATE':\n return t('content.issues.duplicate');\n case 'UNKNOWN_FIELD':\n return t('content.issues.unknownField');\n case 'UNKNOWN_COMPONENT':\n return t('content.issues.unknownComponent');\n case 'INVALID_RICHTEXT':\n return t('content.issues.invalidRichText');\n case 'NOT_UNIQUE':\n return t('content.issues.notUnique');\n case 'RELATION_TARGET_MISSING':\n return t('content.issues.relationMissing');\n case 'MEDIA_MISSING':\n return t('content.issues.mediaMissing');\n case 'INVALID_JSON':\n return t('content.issues.invalidJson');\n default:\n return issue.message;\n }\n};\n","import { i18next } from '@/app/i18n';\nimport type { BuiltInEditorProps } from '../types';\nimport { stringOption } from './props';\n\nexport type Choice = { value: string; label: string };\n\n/** The choices of an enum (labels are content, shown as authored) or a boolean (Yes/No or custom labels). */\nexport const choicesOf = (props: BuiltInEditorProps): Choice[] => {\n const { definition } = props;\n if (definition.type === 'enum') {\n return definition.settings.values.map(({ value, label }) => ({ value, label }));\n }\n return [\n { value: 'true', label: stringOption(props, 'trueLabel') ?? i18next.t('content.fields.yes') },\n { value: 'false', label: stringOption(props, 'falseLabel') ?? i18next.t('content.fields.no') },\n ];\n};\n\n/** Choice value (always a string in the control) → field value. */\nexport const fromChoice = (props: BuiltInEditorProps, choice: string): unknown => {\n if (choice === '') {\n return null;\n }\n return props.definition.type === 'boolean' ? choice === 'true' : choice;\n};\n\nexport const toChoice = (value: unknown): string =>\n typeof value === 'boolean' ? String(value) : typeof value === 'string' ? value : '';\n\nexport const isMultiple = (props: BuiltInEditorProps) =>\n props.definition.type === 'enum' && props.definition.settings.multiple;\n","import { Checkbox } from '@/components/ui/checkbox';\nimport { Label } from '@/components/ui/label';\nimport { cn } from '@/helpers/cn';\nimport { choicesOf } from '../helpers/choices';\nimport { stringOption } from '../helpers/props';\nimport { toList } from '../helpers/values';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `checkboxGroup`: one checkbox per value of a multiple-choice enum. Values keep the enum's order. */\nexport const CheckboxGroup = (props: BuiltInEditorProps) => {\n const { inputId, labelId, describedBy, value, onChange, onBlur, readOnly, disabled, validation } = props;\n const selected = toList<string>(value);\n const choices = choicesOf(props);\n const horizontal = stringOption(props, 'layout') === 'horizontal';\n return (\n <div\n role=\"group\"\n aria-labelledby={labelId}\n aria-describedby={describedBy}\n aria-invalid={validation.invalid || undefined}\n className={cn('grid gap-2', horizontal && 'flex flex-wrap gap-x-6')}\n onBlur={onBlur}\n >\n {choices.map((choice) => (\n <div key={choice.value} className=\"flex items-center gap-2\">\n <Checkbox\n id={`${inputId}-${choice.value}`}\n checked={selected.includes(choice.value)}\n disabled={disabled || readOnly}\n onCheckedChange={(checked) => {\n const next = choices\n .map((item) => item.value)\n .filter((item) => (item === choice.value ? checked === true : selected.includes(item)));\n onChange(next.length > 0 ? next : null);\n }}\n />\n <Label htmlFor={`${inputId}-${choice.value}`} className=\"font-normal\">\n {choice.label}\n </Label>\n </div>\n ))}\n </div>\n );\n};\n","import { Checkbox } from '@/components/ui/checkbox';\nimport { inputAria } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `checkbox`: a checkbox for booleans. */\nexport const CheckboxInput = (props: BuiltInEditorProps) => {\n const { value, onChange, onBlur, readOnly, disabled } = props;\n return (\n <Checkbox\n {...inputAria(props)}\n checked={value === true}\n disabled={disabled || readOnly}\n onCheckedChange={(checked) => onChange(checked === true)}\n onBlur={onBlur}\n />\n );\n};\n","import type { CSSProperties } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Input } from '@/components/ui/input';\nimport { cn } from '@/helpers/cn';\nimport { inputAria, textValue } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\nconst HEX_COLOUR = /^#[0-9a-f]{6}$/i;\n/** The native picker needs some value when the field is empty or not hex; black, built so no hex literal appears. */\nconst EMPTY_PICKER_VALUE = `#${'0'.repeat(6)}`;\n\nconst presetsOf = (props: BuiltInEditorProps): string[] => {\n const presets = props.field.options.presets;\n return Array.isArray(presets)\n ? presets.filter((preset): preset is string => typeof preset === 'string')\n : [];\n};\n\n/** A swatch shows a user-chosen colour: the one dynamic value, passed through a CSS variable. */\nconst swatchStyle = (colour: string) => ({ '--swatch': colour }) as CSSProperties;\n\n/** `color`: a colour stored as text (hex or `rgb(…)`), with a picker and the field's preset swatches. */\nexport const ColorInput = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { value, onChange, onBlur, readOnly, disabled, field } = props;\n const text = textValue(value);\n const presets = presetsOf(props);\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <input\n type=\"color\"\n aria-label={t('content.fields.color.picker', { field: field.label })}\n value={HEX_COLOUR.test(text) ? text.toLowerCase() : EMPTY_PICKER_VALUE}\n disabled={disabled || readOnly}\n className=\"size-10 shrink-0 cursor-pointer rounded-lg border border-input bg-transparent p-1 disabled:cursor-not-allowed\"\n onChange={(event) => onChange(event.target.value)}\n />\n <Input\n {...inputAria(props)}\n value={text}\n spellCheck={false}\n readOnly={readOnly}\n disabled={disabled}\n className=\"max-w-48 font-mono text-sm\"\n onChange={(event) => onChange(event.target.value === '' ? null : event.target.value)}\n onBlur={onBlur}\n />\n </div>\n {presets.length > 0 ? (\n <div role=\"group\" aria-label={t('content.fields.color.presets')} className=\"flex flex-wrap gap-1.5\">\n {presets.map((preset) => (\n <button\n key={preset}\n type=\"button\"\n aria-label={preset}\n aria-pressed={preset.toLowerCase() === text.toLowerCase()}\n disabled={disabled || readOnly}\n style={swatchStyle(preset)}\n className={cn(\n 'size-7 rounded-md border border-input bg-(--swatch) outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n preset.toLowerCase() === text.toLowerCase() &&\n 'ring-2 ring-ring ring-offset-2 ring-offset-background',\n )}\n onClick={() => onChange(preset)}\n />\n ))}\n </div>\n ) : null}\n </div>\n );\n};\n","import { Plus } from 'lucide-react';\nimport type { ComponentProps } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/helpers/cn';\n\ntype AddItemButtonProps = Omit<ComponentProps<typeof Button>, 'children' | 'size' | 'variant'> & {\n /** \"Add Text item\", \"Add section\". */\n label: string;\n /** `outline` in forms and empty states; `ghost` at the end of a canvas list, like the canvas's own `+`. */\n variant?: 'outline' | 'ghost';\n};\n\n/**\n * Adds to a list (or fills an empty single component). Passes its other props to the button, so it can be\n * a menu's trigger (`asChild`).\n */\nexport const AddItemButton = ({ label, variant = 'outline', className, ...props }: AddItemButtonProps) => (\n <Button\n type=\"button\"\n variant={variant}\n size=\"sm\"\n className={cn(variant === 'ghost' && '-ml-2 text-muted-foreground', className)}\n {...props}\n >\n <Plus aria-hidden=\"true\" />\n {label}\n </Button>\n);\n","import { Globe, Languages } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { cn } from '@/helpers/cn';\n\ntype ScopeBadgeProps = { localized: boolean };\n\nconst CHIP_CLASSES =\n 'inline-flex h-5 items-center gap-1 rounded-full px-2 text-2xs font-semibold [&_svg]:size-3 [&_svg]:shrink-0';\n\n/**\n * In a localized model, says whether a field is per locale or shared by every locale of the entry. Shared\n * fields explain themselves on click (saving one changes every locale's draft, ADR 0004).\n */\nexport const ScopeBadge = ({ localized }: ScopeBadgeProps) => {\n const { t } = useTranslation();\n if (localized) {\n return (\n <span className={cn(CHIP_CLASSES, 'bg-accent text-accent-foreground')}>\n <Languages aria-hidden=\"true\" />\n {t('content.scope.localized')}\n </span>\n );\n }\n return (\n <Popover>\n <PopoverTrigger\n type=\"button\"\n className={cn(\n CHIP_CLASSES,\n 'border text-muted-foreground outline-none hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50',\n )}\n >\n <Globe aria-hidden=\"true\" />\n {t('content.scope.shared')}\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 p-3 text-meta\">\n {t('content.scope.sharedHint')}\n </PopoverContent>\n </Popover>\n );\n};\n","import { Globe, Languages } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { cn } from '@/helpers/cn';\n\ntype ScopeIconProps = { localized: boolean; className?: string };\n\n/**\n * The document's quiet version of `ScopeBadge`: a 14px icon saying whether a value is per locale or shared\n * by every locale (ADR 0004). Its name is in a tooltip and in text for screen readers.\n */\nexport const ScopeIcon = ({ localized, className }: ScopeIconProps) => {\n const { t } = useTranslation();\n const Icon = localized ? Languages : Globe;\n const label = localized ? t('content.scope.localized') : t('content.scope.sharedHint');\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n className={cn('inline-flex shrink-0 text-muted-foreground [&_svg]:size-3.5', className)}\n data-scope={localized ? 'localized' : 'shared'}\n >\n <Icon aria-hidden=\"true\" />\n <span className=\"sr-only\">{label}</span>\n </span>\n </TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n );\n};\n","import type { FieldDefinition, SchemaDefinition } from '@shapio/schema';\nimport { memo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Label } from '@/components/ui/label';\nimport { cn } from '@/helpers/cn';\nimport { FieldEditor } from '../FieldEditor';\nimport { FieldMessages } from '../FieldMessages';\nimport { useFieldsEnvironment } from '../form/context';\nimport { useFieldControl } from '../hooks/useFieldControl';\nimport { ScopeBadge } from '../ScopeBadge';\nimport { ScopeIcon } from '../ScopeIcon';\n\nexport type FieldLayout = 'stacked' | 'inline' | 'bare';\n\ntype FieldControlProps = {\n field: FieldDefinition;\n /** The model or component the field belongs to. */\n owner: SchemaDefinition;\n value: unknown;\n onChange: (value: unknown) => void;\n /** JSON pointer of the value, e.g. `/hero/title` (issues use the same paths). */\n path: string;\n /** A field of the entry itself (shows the localized/shared badge in localized models). */\n topLevel: boolean;\n /**\n * `stacked` (default): label above the editor (forms, the settings drawer). `inline`: a small label beside\n * the value, a line of a document (the property grid, component blocks in the canvas). `bare`: the\n * label only names the control (the settings drawer's row already shows it).\n */\n layout?: FieldLayout;\n className?: string;\n};\n\n/**\n * One field in a form: label (with the localized/shared badge), the editor the field's definition chooses,\n * help text and inline errors.\n */\nexport const FieldControl = memo(\n ({ field, owner, value, onChange, path, topLevel, layout = 'stacked', className }: FieldControlProps) => {\n const { t } = useTranslation();\n const environment = useFieldsEnvironment();\n const control = useFieldControl({ field, owner, value, onChange, path });\n const LabelElement = control.labelling === 'input' ? Label : 'span';\n const inline = layout === 'inline';\n return (\n <div\n className={cn(\n 'min-w-0 scroll-mt-24',\n inline ? 'grid gap-x-4 gap-y-1 sm:grid-cols-[9rem_minmax(0,1fr)]' : 'space-y-2',\n className,\n )}\n id={`${control.inputId}-section`}\n data-field-path={path}\n >\n <div\n className={cn(\n 'flex min-h-5 flex-wrap items-center gap-2',\n inline && 'sm:min-h-10 sm:pt-0.5',\n layout === 'bare' && 'sr-only',\n )}\n >\n <LabelElement\n id={control.labelId}\n {...(control.labelling === 'input' ? { htmlFor: control.inputId } : {})}\n className={cn(\n 'leading-5',\n inline ? 'text-meta font-medium text-muted-foreground' : 'text-sm font-semibold',\n )}\n >\n {field.label}\n {field.required ? (\n <>\n <span aria-hidden=\"true\" className=\"ml-0.5 text-destructive\">\n *\n </span>\n <span className=\"sr-only\">{t('content.fields.required')}</span>\n </>\n ) : null}\n </LabelElement>\n {topLevel && environment.model.localized ? (\n inline ? (\n <ScopeIcon localized={field.localized} />\n ) : (\n <ScopeBadge localized={field.localized} />\n )\n ) : null}\n </div>\n <div className=\"min-w-0 space-y-2\">\n <FieldEditor control={control} />\n <FieldMessages field={field} control={control} />\n </div>\n </div>\n );\n },\n);\n\nFieldControl.displayName = 'FieldControl';\n","import { entryLayoutOf, type FieldWidth, type ModelDefinition } from '@shapio/schema';\n\n/**\n * The six-column grid a form-layout entry lays its fields on (`FieldGrid` in width mode). A container query,\n * not a viewport breakpoint: below `@lg` (32rem) of the form column every field takes the whole row. `@lg`\n * keeps the row with the settings drawer open on a 1440px screen, where the column is about 630px wide.\n */\nexport const WIDTH_GRID_CLASSES = 'grid gap-5 @lg:grid-cols-6';\n\n/** How many of the grid's six columns a field spans at each `FieldWidth`. Full class strings, never built. */\nexport const WIDTH_CLASSES = {\n full: '@lg:col-span-6',\n 'two-thirds': '@lg:col-span-4',\n half: '@lg:col-span-3',\n third: '@lg:col-span-2',\n} as const satisfies Record<FieldWidth, string>;\n\n/** The span classes of a field's width; unset is `full`. */\nexport const widthClassOf = (width: FieldWidth | undefined): string => WIDTH_CLASSES[width ?? 'full'];\n\n/**\n * How `FieldGrid` lays out a model's own fields: `compact` pairs short values up automatically (component\n * items, quick edit, a document-layout model); `widths` spans each field by its `width` (a form-layout model).\n */\nexport type FieldGridMode = 'compact' | 'widths';\n\n/** The grid mode for an entry's own fields: `widths` when the model opens as a form. */\nexport const fieldGridModeOf = (model: ModelDefinition): FieldGridMode =>\n entryLayoutOf(model) === 'form' ? 'widths' : 'compact';\n","import type { FieldDefinition } from '@shapio/schema';\nimport type { ReactNode } from 'react';\nimport { WIDTH_GRID_CLASSES, widthClassOf, type FieldGridMode } from '../helpers/widthClasses';\n\ntype FieldGridProps = {\n fields: readonly FieldDefinition[];\n renderField: (field: FieldDefinition, className: string) => ReactNode;\n /** `compact` (default) or `widths`; see `FieldGridMode`. */\n mode?: FieldGridMode;\n};\n\n/**\n * Short values sit two to a row when the form column itself is wide (title + slug, like the mockup); the\n * rest span the row. A container query, not a viewport breakpoint: the entry form's centre column sits\n * between two side panels, and splitting it on a wide screen left inputs a third of the column wide.\n */\nconst COMPACT_TYPES: ReadonlySet<string> = new Set([\n 'string',\n 'slug',\n 'email',\n 'url',\n 'uid',\n 'number',\n 'integer',\n 'decimal',\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'time',\n]);\n\nconst isCompact = (field: FieldDefinition) =>\n COMPACT_TYPES.has(field.type) || (field.type === 'enum' && field.editor.id === 'select');\n\nexport const FieldGrid = ({ fields, renderField, mode = 'compact' }: FieldGridProps) => (\n <div className=\"@container\">\n {mode === 'widths' ? (\n <div className={WIDTH_GRID_CLASSES}>\n {fields.map((field) => renderField(field, widthClassOf(field.width)))}\n </div>\n ) : (\n <div className=\"grid gap-5 @2xl:grid-cols-2\">\n {fields.map((field) => renderField(field, isCompact(field) ? '@2xl:col-span-1' : '@2xl:col-span-2'))}\n </div>\n )}\n </div>\n);\n","import type { MediaAsset } from '@shapio/client';\nimport type { ComponentDefinition, FieldDefinition } from '@shapio/schema';\nimport {\n COMPONENT_KEY,\n isEmptyValue,\n isRecord,\n isSameContent,\n stripClientKeys,\n withClientKey,\n type FormValues,\n type ItemValues,\n} from './values';\n\n/**\n * Conversion between the admin API's entry data and the form's values. Reads return media fields as asset\n * views (`{ id, url, ... }`); the form and every write use asset IDs, so editors (custom ones included)\n * always see the same value the server validates.\n */\nexport type ComponentLookup = ReadonlyMap<string, ComponentDefinition>;\n\ntype Collect = (asset: MediaAsset) => void;\n\nconst isAssetView = (value: unknown): value is MediaAsset =>\n isRecord(value) && typeof value.id === 'string' && typeof value.url === 'string';\n\nconst mediaIdOf = (value: unknown, collect: Collect | undefined): string | null => {\n if (typeof value === 'string') {\n return value;\n }\n if (isAssetView(value)) {\n collect?.(value);\n return value.id;\n }\n return null;\n};\n\nexport const liveFields = (fields: readonly FieldDefinition[]) => fields.filter((field) => !field.deprecated);\n\nconst componentOfItem = (\n field: FieldDefinition<'dynamiczone'>,\n item: ItemValues,\n components: ComponentLookup,\n): ComponentDefinition | undefined =>\n field.settings.components\n .map((id) => components.get(id))\n .find((component) => component?.apiKey === item[COMPONENT_KEY]);\n\nconst fromApiValue = (\n field: FieldDefinition,\n value: unknown,\n components: ComponentLookup,\n collect: Collect | undefined,\n): unknown => {\n if (value === undefined || value === null) {\n return null;\n }\n switch (field.type) {\n case 'media':\n return Array.isArray(value)\n ? value.map((item) => mediaIdOf(item, collect)).filter((id): id is string => id !== null)\n : mediaIdOf(value, collect);\n case 'component': {\n const component = components.get(field.settings.component);\n const convert = (item: unknown) =>\n withClientKey(\n component && isRecord(item) ? toFormValues(component.fields, item, components, collect) : {},\n );\n return field.settings.repeatable ? (Array.isArray(value) ? value.map(convert) : []) : convert(value);\n }\n case 'dynamiczone':\n return (Array.isArray(value) ? value : []).filter(isRecord).map((item) => {\n const component = componentOfItem(field, item, components);\n return withClientKey({\n [COMPONENT_KEY]: item[COMPONENT_KEY],\n ...(component ? toFormValues(component.fields, item, components, collect) : {}),\n });\n });\n default:\n return value;\n }\n};\n\n/** API data (one model or component level) → form values. `collect` receives every media asset view seen. */\nexport function toFormValues(\n fields: readonly FieldDefinition[],\n data: Readonly<Record<string, unknown>>,\n components: ComponentLookup,\n collect?: Collect,\n): FormValues {\n const values: FormValues = {};\n for (const field of liveFields(fields)) {\n values[field.apiKey] = fromApiValue(field, data[field.apiKey], components, collect);\n }\n return values;\n}\n\n/** Initial values for a new entry or component item: each field's default, or empty. */\nexport const defaultFormValues = (fields: readonly FieldDefinition[]): FormValues =>\n Object.fromEntries(\n liveFields(fields).map((field) => [field.apiKey, structuredClone(field.defaultValue ?? null) as unknown]),\n );\n\nexport const newComponentItem = (component: ComponentDefinition, zoned: boolean): ItemValues =>\n withClientKey({\n ...(zoned ? { [COMPONENT_KEY]: component.apiKey } : {}),\n ...defaultFormValues(component.fields),\n });\n\n/** A form value as the API takes it: client keys stripped, empty values sent as null (= clear). */\nexport const toInputValue = (value: unknown): unknown =>\n isEmptyValue(value) ? null : stripClientKeys(value);\n\n/** Top-level API keys whose value differs from the baseline (what the last load or save returned). */\nexport const dirtyKeysOf = (values: FormValues, baseline: FormValues): string[] =>\n Object.keys(values).filter((key) => !isSameContent(values[key], baseline[key]));\n\n/** The PUT body's `data`: changed fields only (the API treats it as a patch). */\nexport const buildPatch = (values: FormValues, keys: readonly string[]): Record<string, unknown> =>\n Object.fromEntries(keys.map((key) => [key, toInputValue(values[key])]));\n\n/** Every non-empty value, for creating an entry. */\nexport const buildCreateData = (values: FormValues): Record<string, unknown> =>\n Object.fromEntries(\n Object.entries(values)\n .filter(([, value]) => !isEmptyValue(value))\n .map(([key, value]) => [key, stripClientKeys(value)]),\n );\n\n/**\n * After a save: the server's values become the baseline. Fields the person did not touch while the save\n * was in flight take the server's (canonical) value, keeping the current object when the content is the\n * same so list items keep their client keys; fields edited meanwhile keep the newer local value.\n */\nexport const mergeSaved = (\n current: FormValues,\n sent: FormValues,\n saved: FormValues,\n): { values: FormValues; baseline: FormValues } => {\n const values: FormValues = { ...current };\n const baseline: FormValues = { ...saved };\n for (const key of Object.keys(saved)) {\n const editedMeanwhile = !Object.is(current[key], sent[key]);\n if (editedMeanwhile) {\n continue;\n }\n if (isSameContent(current[key], saved[key])) {\n baseline[key] = current[key];\n } else {\n values[key] = saved[key];\n }\n }\n return { values, baseline };\n};\n","import type { ComponentDefinition, FieldDefinition } from '@shapio/schema';\nimport { useMemo, type ReactNode } from 'react';\nimport { cn } from '@/helpers/cn';\nimport { FieldControl } from '../FieldControl';\nimport { FieldGrid } from '../FieldGrid';\nimport { SiblingValuesContext } from '../form/context';\nimport { liveFields } from '../helpers/formValues';\nimport { pointerOf } from '../helpers/issues';\nimport type { ItemValues } from '../helpers/values';\n\ntype ComponentItemFieldsProps = {\n component: ComponentDefinition;\n item: ItemValues;\n onItemChange: (item: ItemValues) => void;\n /** Pointer of the item, e.g. `/hero` or `/sections/2`. */\n path: string;\n /** `document`: label + value lines, as a component block in the entry canvas. */\n layout?: 'form' | 'document';\n /** Extra content under a field (the SEO editor's length counters), keyed on the field's stable ID. */\n renderFieldFooter?: (field: FieldDefinition, value: unknown) => ReactNode;\n};\n\n/** The fields of one component value (a single component, a repeatable item or a dynamic-zone item). */\nexport const ComponentItemFields = ({\n component,\n item,\n onItemChange,\n path,\n layout = 'form',\n renderFieldFooter,\n}: ComponentItemFieldsProps) => {\n const siblings = useMemo(() => ({ definition: component, values: item }), [component, item]);\n const fields = liveFields(component.fields);\n const renderField = (field: FieldDefinition, className?: string) => {\n // Always wrapped when footers are on: a footer appearing must not remount the control (focus would go).\n const wrapped = renderFieldFooter !== undefined;\n const control = (\n <FieldControl\n key={field.id}\n field={field}\n owner={component}\n value={item[field.apiKey]}\n onChange={(next) => onItemChange({ ...item, [field.apiKey]: next })}\n path={pointerOf(path, field.apiKey)}\n topLevel={false}\n layout={layout === 'document' ? 'inline' : 'stacked'}\n className={wrapped ? undefined : className}\n />\n );\n return wrapped ? (\n <div key={field.id} className={cn('min-w-0 space-y-1.5', className)}>\n {control}\n {renderFieldFooter(field, item[field.apiKey])}\n </div>\n ) : (\n control\n );\n };\n return (\n <SiblingValuesContext.Provider value={siblings}>\n {layout === 'document' ? (\n <div className=\"space-y-3\">{fields.map((field) => renderField(field))}</div>\n ) : (\n <FieldGrid fields={fields} renderField={renderField} />\n )}\n </SiblingValuesContext.Provider>\n );\n};\n","import { richTextPlainText, type ComponentDefinition, type FieldDefinition } from '@shapio/schema';\nimport { i18next } from '@/app/i18n';\nimport { valueLabel } from '@/features/Models/helpers/labels';\nimport { isEmptyValue, isRecord, toList } from './values';\n\n/**\n * A short, readable summary of a value for collapsed component items, dynamic-zone outlines, list cells\n * and revision diffs. Plain text only; never markup from the content.\n */\nconst MAX_SUMMARY = 80;\n\nconst truncate = (text: string) => (text.length > MAX_SUMMARY ? `${text.slice(0, MAX_SUMMARY - 1)}…` : text);\n\nexport const summarizeValue = (field: FieldDefinition, value: unknown): string => {\n if (isEmptyValue(value)) {\n return '';\n }\n switch (field.type) {\n case 'richtext':\n return truncate(richTextPlainText(value));\n case 'boolean':\n return value === true ? '✓' : '✗';\n case 'enum':\n return toList<string>(value)\n .map((item) => field.settings.values.find((option) => option.value === item)?.label ?? item)\n .join(', ');\n case 'json':\n return truncate(JSON.stringify(value));\n case 'code':\n // A snippet reads badly as a label: its language and size instead (\"HTML, 14 lines\").\n return i18next.t('content.fields.code.summary', {\n language: valueLabel(field.settings.language),\n count: String(value).split('\\n').length,\n });\n case 'media':\n case 'relation':\n case 'component':\n case 'dynamiczone':\n return String(toList(value).length);\n default:\n return truncate(String(value));\n }\n};\n\nconst TEXTUAL_TYPES: ReadonlySet<string> = new Set(['string', 'text', 'slug', 'email', 'url', 'uid', 'enum']);\n\n/** A component item's label: its title field's value, else the first non-empty text field. */\nexport const summarizeItem = (component: ComponentDefinition, item: unknown): string => {\n if (!isRecord(item)) {\n return '';\n }\n const titleField = component.fields.find((field) => field.id === component.display.titleFieldId);\n const candidates = titleField ? [titleField, ...component.fields] : component.fields;\n for (const field of candidates) {\n if (TEXTUAL_TYPES.has(field.type) || field.type === 'richtext') {\n const summary = summarizeValue(field, item[field.apiKey]);\n if (summary) {\n return summary;\n }\n }\n }\n return '';\n};\n","import { useCallback, useState } from 'react';\n\n/** Which list items are collapsed, by client key. New items are expanded; `startCollapsed` applies to loaded ones. */\nexport const useCollapsedItems = (initialKeys: readonly string[], startCollapsed: boolean) => {\n const [collapsed, setCollapsed] = useState<ReadonlySet<string>>(\n () => new Set(startCollapsed ? initialKeys : []),\n );\n const toggle = useCallback(\n (key: string) =>\n setCollapsed((current) => {\n const next = new Set(current);\n if (next.has(key)) {\n next.delete(key);\n } else {\n next.add(key);\n }\n return next;\n }),\n [],\n );\n const setAll = useCallback(\n (keys: readonly string[], value: boolean) => setCollapsed(new Set(value ? keys : [])),\n [],\n );\n return { collapsed, toggle, setAll };\n};\n","import { useEffect, useRef } from 'react';\n\n/** After an item is added, moves focus to its header so keyboard users land on what they created. */\nexport const useFocusNewItem = (keys: readonly string[], domId: (key: string) => string) => {\n const previous = useRef(keys);\n useEffect(() => {\n const added = keys.find((key) => !previous.current.includes(key));\n previous.current = keys;\n if (added && keys.length > 0) {\n document.getElementById(domId(added))?.querySelector<HTMLElement>('button[aria-expanded]')?.focus();\n }\n }, [keys, domId]);\n};\n","import { useState, type DragEvent } from 'react';\n\nconst DRAG_TYPE = 'application/x-shapio-item';\n\n/**\n * Native HTML5 drag to reorder the items of one list (component blocks in the canvas). Only drags that\n * started in this list are accepted, so files or other lists' items never drop here. ⌥↑ / ⌥↓ and the move\n * buttons do the same from the keyboard.\n */\nexport const useItemDrag = (move: (from: number, to: number) => void) => {\n const [from, setFrom] = useState<number | null>(null);\n const [over, setOver] = useState<number | null>(null);\n const reset = () => {\n setFrom(null);\n setOver(null);\n };\n return {\n handleProps: (index: number) => ({\n draggable: true,\n onDragStart: (event: DragEvent) => {\n setFrom(index);\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData(DRAG_TYPE, String(index));\n const item = (event.currentTarget as HTMLElement).closest('li');\n if (item) {\n event.dataTransfer.setDragImage(item, 16, 16);\n }\n },\n onDragEnd: reset,\n }),\n targetProps: (index: number) => ({\n onDragOver: (event: DragEvent) => {\n if (from === null || !event.dataTransfer.types.includes(DRAG_TYPE)) {\n return;\n }\n event.preventDefault();\n event.dataTransfer.dropEffect = 'move';\n setOver(index);\n },\n onDrop: (event: DragEvent) => {\n if (from === null) {\n return;\n }\n event.preventDefault();\n if (from !== index) {\n move(from, index);\n }\n reset();\n },\n }),\n /** Where the dragged item would land: before (moving up) or after (moving down) this item. */\n dropSide: (index: number): 'before' | 'after' | undefined =>\n from === null || over !== index || from === index ? undefined : from > index ? 'before' : 'after',\n };\n};\n","import { useMemo } from 'react';\nimport { useEntryForm } from '../form/context';\nimport { countIssuesUnder, issuesByPath } from '../helpers/issues';\n\n/** Server issues at or below a path (shown on collapsed items so problems are never hidden). */\nexport const useItemIssueCount = (path: string): number => {\n const issues = useEntryForm((state) => state.issues);\n return useMemo(() => countIssuesUnder(issuesByPath(issues), path), [issues, path]);\n};\n","import { ArrowDown, ArrowUp, ChevronRight, Copy, GripVertical, Trash2 } from 'lucide-react';\nimport type { DragEvent, KeyboardEvent, ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { StatusChip } from '@/components/StatusChip';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/helpers/cn';\n\ntype ItemCardProps = {\n id: string;\n title: string;\n summary: string;\n index: number;\n count: number;\n collapsed: boolean;\n issueCount: number;\n editable: boolean;\n onToggle: () => void;\n onMove?: (to: number) => void;\n onDuplicate?: () => void;\n onRemove?: () => void;\n /**\n * `canvas`: a block of the entry document: quiet chrome, actions on hover or focus, a drag grip.\n * Requires `drag` for the grip and the drop target.\n */\n appearance?: 'form' | 'canvas';\n drag?: {\n handle: { draggable: boolean; onDragStart: (event: DragEvent) => void; onDragEnd: () => void };\n target: { onDragOver: (event: DragEvent) => void; onDrop: (event: DragEvent) => void };\n dropSide: 'before' | 'after' | undefined;\n };\n children: ReactNode;\n};\n\n/**\n * One item of a repeatable component or dynamic zone: a header that collapses it (with a readable summary\n * and its problem count), move, duplicate and remove actions, and the item's fields. Alt+↑/↓ on the header\n * moves the item.\n */\nexport const ItemCard = ({\n id,\n title,\n summary,\n index,\n count,\n collapsed,\n issueCount,\n editable,\n onToggle,\n onMove,\n onDuplicate,\n onRemove,\n appearance = 'form',\n drag,\n children,\n}: ItemCardProps) => {\n const { t } = useTranslation();\n const bodyId = `${id}-body`;\n const onKeyDown = (event: KeyboardEvent) => {\n if (!event.altKey || !onMove) {\n return;\n }\n if (event.key === 'ArrowUp' && index > 0) {\n event.preventDefault();\n onMove(index - 1);\n } else if (event.key === 'ArrowDown' && index < count - 1) {\n event.preventDefault();\n onMove(index + 1);\n }\n };\n const canvas = appearance === 'canvas';\n // On the canvas the actions appear on hover, and stay while anything in the block has focus.\n const actionClasses = canvas\n ? 'opacity-0 transition-opacity group-focus-within/item:opacity-100 group-hover/item:opacity-100'\n : undefined;\n return (\n <li\n id={id}\n className={cn(\n 'group/item scroll-mt-32 rounded-xl border bg-card data-invalid:border-destructive/60',\n canvas && 'border-transparent bg-muted/40 focus-within:border-border hover:border-border',\n drag?.dropSide === 'before' && 'shadow-[0_-3px_0_0_var(--color-ring)]',\n drag?.dropSide === 'after' && 'shadow-[0_3px_0_0_var(--color-ring)]',\n )}\n data-invalid={issueCount > 0 || undefined}\n {...(canvas ? drag?.target : {})}\n >\n <div className=\"flex items-center gap-1 py-1.5 pr-2 pl-1.5\">\n {canvas && editable && drag ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n className={cn('cursor-grab text-muted-foreground active:cursor-grabbing', actionClasses)}\n aria-label={t('entry.blocks.dragItem', { item: title, position: index + 1 })}\n {...drag.handle}\n >\n <GripVertical aria-hidden=\"true\" />\n </Button>\n ) : null}\n <button\n type=\"button\"\n aria-expanded={!collapsed}\n aria-controls={bodyId}\n onClick={onToggle}\n onKeyDown={onKeyDown}\n className=\"flex h-8 min-w-0 flex-1 items-center gap-2 rounded-lg px-2 text-left outline-none hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n >\n <ChevronRight\n aria-hidden=\"true\"\n className={cn(\n 'size-4 shrink-0 text-muted-foreground transition-transform',\n !collapsed && 'rotate-90',\n )}\n />\n <span className=\"shrink-0 text-sm font-semibold\">{title}</span>\n {summary ? (\n <span className=\"min-w-0 truncate text-meta text-muted-foreground\">{summary}</span>\n ) : null}\n <span className=\"sr-only\">{t('content.items.position', { index: index + 1, count })}</span>\n </button>\n {issueCount > 0 ? (\n <StatusChip tone=\"danger\" size=\"sm\" label={t('content.items.problems', { count: issueCount })} />\n ) : null}\n <span className={cn('flex items-center gap-1', actionClasses)}>\n {editable && onMove ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.moveUp', { item: title, position: index + 1 })}\n disabled={index === 0}\n onClick={() => onMove(index - 1)}\n >\n <ArrowUp aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.moveDown', { item: title, position: index + 1 })}\n disabled={index === count - 1}\n onClick={() => onMove(index + 1)}\n >\n <ArrowDown aria-hidden=\"true\" />\n </Button>\n </>\n ) : null}\n {editable && onDuplicate ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.duplicate', { item: title, position: index + 1 })}\n onClick={onDuplicate}\n >\n <Copy aria-hidden=\"true\" />\n </Button>\n ) : null}\n {editable && onRemove ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.remove', { item: title, position: index + 1 })}\n onClick={onRemove}\n >\n <Trash2 aria-hidden=\"true\" />\n </Button>\n ) : null}\n </span>\n </div>\n <div id={bodyId} hidden={collapsed} className={cn(canvas ? 'px-4 pt-1 pb-4' : 'border-t p-5')}>\n {collapsed ? null : children}\n </div>\n </li>\n );\n};\n","import type { ComponentDefinition } from '@shapio/schema';\nimport { Boxes, Plus } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { useDeferredMenuAction } from '../hooks/useDeferredMenuAction';\nimport { InsertMenuItem } from '../InsertMenuItem';\n\ntype ItemInserterProps = {\n /** The components that can be stored here (a zone's allowed ones, or the repeatable's one). */\n components: readonly ComponentDefinition[];\n /** Where the new block goes, for its name (\"Add a block before item 2\"). */\n position: number;\n onInsert: (component: ComponentDefinition) => void;\n};\n\n/**\n * An insertion point between two component blocks of the canvas: a hairline with `+` that shows on hover\n * or keyboard focus and offers only what this list can hold.\n */\nexport const ItemInserter = ({ components, position, onInsert }: ItemInserterProps) => {\n const { t } = useTranslation();\n const menu = useDeferredMenuAction();\n return (\n <li className=\"group/inserter relative flex h-4 items-center\" data-item-inserter>\n <span\n aria-hidden=\"true\"\n className=\"h-px flex-1 bg-border opacity-0 transition-opacity group-focus-within/inserter:opacity-100 group-hover/inserter:opacity-100\"\n />\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon-xs\"\n className=\"absolute left-1/2 -translate-x-1/2 rounded-full bg-background opacity-0 transition-opacity group-hover/inserter:opacity-100 focus-visible:opacity-100 data-[state=open]:opacity-100\"\n aria-label={t('entry.blocks.insertAt', { position })}\n >\n <Plus aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"center\" className=\"w-72\" onCloseAutoFocus={menu.onCloseAutoFocus}>\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n {t('entry.blocks.groupComponents')}\n </DropdownMenuLabel>\n {components.map((component) => (\n <InsertMenuItem\n key={component.id}\n icon={Boxes}\n label={component.label}\n onSelect={() => menu.defer(() => onInsert(component))}\n />\n ))}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </li>\n );\n};\n","import type { ComponentDefinition } from '@shapio/schema';\nimport { Fragment, useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { ComponentItemFields } from '../ComponentItemFields';\nimport { pointerOf } from '../helpers/issues';\nimport { summarizeItem } from '../helpers/summary';\nimport { COMPONENT_KEY, type ItemValues } from '../helpers/values';\nimport { useCollapsedItems } from '../hooks/useCollapsedItems';\nimport { useFocusNewItem } from '../hooks/useFocusNewItem';\nimport { useItemDrag } from '../hooks/useItemDrag';\nimport { useItemIssueCount } from '../hooks/useItemIssueCount';\nimport type { useListEditor } from '../hooks/useListEditor';\nimport { ItemCard } from '../ItemCard';\nimport { ItemInserter } from '../ItemInserter';\n\ntype ListEditor = ReturnType<typeof useListEditor>;\n\ntype CanvasItemListProps = {\n list: ListEditor;\n labelId: string;\n inputId: string;\n path: string;\n editable: boolean;\n /** What can be inserted between blocks (empty when the list is full). */\n insertable: readonly ComponentDefinition[];\n /** The component an item is (a zone item's `__component`, or the repeatable's one). */\n componentOf: (item: ItemValues) => ComponentDefinition | undefined;\n newItem: (component: ComponentDefinition) => ItemValues;\n startCollapsed: boolean;\n};\n\ntype BlockProps = {\n list: ListEditor;\n item: ItemValues;\n itemKey: string;\n index: number;\n path: string;\n domId: string;\n editable: boolean;\n component: ComponentDefinition | undefined;\n collapsed: boolean;\n onToggle: (key: string) => void;\n drag: ReturnType<typeof useItemDrag>;\n};\n\nconst Block = ({\n list,\n item,\n itemKey,\n index,\n path,\n domId,\n editable,\n component,\n collapsed,\n onToggle,\n drag,\n}: BlockProps) => {\n const { t } = useTranslation();\n const itemPath = pointerOf(path, index);\n const issueCount = useItemIssueCount(itemPath);\n const onItemChange = useCallback((next: ItemValues) => list.update(index, next), [list, index]);\n return (\n <ItemCard\n id={domId}\n appearance=\"canvas\"\n title={component?.label ?? t('content.items.unknownComponent', { key: String(item[COMPONENT_KEY]) })}\n summary={component ? summarizeItem(component, item) : ''}\n index={index}\n count={list.items.length}\n collapsed={collapsed}\n issueCount={issueCount}\n editable={editable}\n onToggle={() => onToggle(itemKey)}\n onMove={(to) => list.move(index, to)}\n onDuplicate={component ? () => list.duplicate(index) : undefined}\n onRemove={() => list.remove(index)}\n drag={{\n handle: drag.handleProps(index),\n target: drag.targetProps(index),\n dropSide: drag.dropSide(index),\n }}\n >\n {component ? (\n <ComponentItemFields\n component={component}\n item={item}\n onItemChange={onItemChange}\n path={itemPath}\n layout=\"document\"\n />\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.items.unknownComponentHint')}</p>\n )}\n </ItemCard>\n );\n};\n\n/**\n * A dynamic zone or repeatable component as blocks of the entry canvas: each item a block with a compact\n * header (actions on hover), its fields as label + value lines, insertion points between blocks, and drag\n * (or ⌥↑↓) to reorder. Adding at the field's start or end is the canvas's boundary inserter.\n */\nexport const CanvasItemList = ({\n list,\n labelId,\n inputId,\n path,\n editable,\n insertable,\n componentOf,\n newItem,\n startCollapsed,\n}: CanvasItemListProps) => {\n const { collapsed, toggle } = useCollapsedItems(list.keys, startCollapsed);\n const domId = useCallback((key: string) => `${inputId}-item-${key}`, [inputId]);\n useFocusNewItem(list.keys, domId);\n const drag = useItemDrag(list.move);\n if (list.items.length === 0) {\n return null;\n }\n return (\n <ol aria-labelledby={labelId} className=\"space-y-1 font-sans\">\n {list.items.map((item, index) => {\n const key = list.keys[index] ?? String(index);\n return (\n <Fragment key={key}>\n {index > 0 && editable && insertable.length > 0 ? (\n <ItemInserter\n components={insertable}\n position={index + 1}\n onInsert={(component) => list.insertAt(index, newItem(component))}\n />\n ) : null}\n <Block\n list={list}\n item={item}\n itemKey={key}\n index={index}\n path={path}\n domId={domId(key)}\n editable={editable}\n component={componentOf(item)}\n collapsed={collapsed.has(key)}\n onToggle={toggle}\n drag={drag}\n />\n </Fragment>\n );\n })}\n </ol>\n );\n};\n","/** Whether a list of `count` items can take one more under its `max` (none: always). */\nexport const hasRoomFor = (count: number, max: number | undefined): boolean =>\n max === undefined || count < max;\n\n/**\n * The count an empty list must reach once it has items, when that changes what the person does: a `min`\n * of 2 or more means one item is not enough. A `min` of 1 says nothing (an empty optional list is valid,\n * and a required one already shows its asterisk), and `max` cannot matter while the list is empty.\n */\nexport const emptyListMinimum = (min: number | undefined): number | undefined =>\n min !== undefined && min > 1 ? min : undefined;\n","import { Boxes } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { EmptyState } from '@/components/EmptyState';\nimport { emptyListMinimum } from '../helpers/listLimits';\n\ntype EmptyListRowProps = {\n /** The list's `min`: named only when one item would not be enough. */\n min: number | undefined;\n /** How to add the first item (none when read-only or full). */\n action: ReactNode;\n};\n\n/** An empty list of the entry canvas: \"Nothing added yet.\" in a dashed row, with its add control. */\nexport const EmptyListRow = ({ min, action }: EmptyListRowProps) => {\n const { t } = useTranslation();\n const minimum = emptyListMinimum(min);\n return (\n <EmptyState\n compact\n icon={Boxes}\n title={t('content.items.empty')}\n description={minimum === undefined ? undefined : t('content.issues.tooFew', { count: minimum })}\n action={action}\n className=\"rounded-xl border border-dashed px-4\"\n />\n );\n};\n","import { useCallback } from 'react';\nimport { clientKeyOf, moveItem, toList, withClientKey, type ItemValues } from '../helpers/values';\n\n/** Add, insert, move, duplicate and remove for list values (repeatable components, dynamic zones). */\nexport const useListEditor = (value: unknown, onChange: (value: unknown) => void) => {\n const items = toList<ItemValues>(value);\n const commit = useCallback((next: ItemValues[]) => onChange(next.length > 0 ? next : null), [onChange]);\n return {\n items,\n keys: items.map((item, index) => clientKeyOf(item, index)),\n add: (item: ItemValues) => commit([...items, item]),\n /** Inserts before `index` (0 = first, `items.length` = last): the canvas's insertion points. */\n insertAt: (index: number, item: ItemValues) => {\n const at = Math.min(Math.max(index, 0), items.length);\n commit([...items.slice(0, at), item, ...items.slice(at)]);\n },\n update: (index: number, item: ItemValues) =>\n commit(items.map((current, at) => (at === index ? item : current))),\n move: (from: number, to: number) => commit(moveItem(items, from, to)),\n duplicate: (index: number) => {\n const copy = withClientKey(structuredClone(items[index] ?? {}));\n commit([...items.slice(0, index + 1), copy, ...items.slice(index + 1)]);\n },\n remove: (index: number) => commit(items.filter((_, at) => at !== index)),\n };\n};\n","import type { ComponentDefinition } from '@shapio/schema';\nimport { Trash2 } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { AddItemButton } from '../AddItemButton';\nimport { CanvasItemList } from '../CanvasItemList';\nimport { ComponentItemFields } from '../ComponentItemFields';\nimport { EmptyListRow } from '../EmptyListRow';\nimport { useFieldsEnvironment } from '../form/context';\nimport { newComponentItem } from '../helpers/formValues';\nimport { pointerOf } from '../helpers/issues';\nimport { hasRoomFor } from '../helpers/listLimits';\nimport { summarizeItem } from '../helpers/summary';\nimport { isRecord, type ItemValues } from '../helpers/values';\nimport { useCollapsedItems } from '../hooks/useCollapsedItems';\nimport { useFocusNewItem } from '../hooks/useFocusNewItem';\nimport { useItemIssueCount } from '../hooks/useItemIssueCount';\nimport { useListEditor } from '../hooks/useListEditor';\nimport { ItemCard } from '../ItemCard';\nimport type { BuiltInEditorProps } from '../types';\n\ntype RepeatableItemProps = {\n component: ComponentDefinition;\n item: ItemValues;\n itemKey: string;\n index: number;\n count: number;\n path: string;\n domId: string;\n collapsed: boolean;\n editable: boolean;\n list: ReturnType<typeof useListEditor>;\n onToggle: (key: string) => void;\n};\n\nconst RepeatableItem = ({\n component,\n item,\n itemKey,\n index,\n count,\n path,\n domId,\n collapsed,\n editable,\n list,\n onToggle,\n}: RepeatableItemProps) => {\n const itemPath = pointerOf(path, index);\n const issueCount = useItemIssueCount(itemPath);\n const onItemChange = useCallback((next: ItemValues) => list.update(index, next), [list, index]);\n return (\n <ItemCard\n id={domId}\n title={component.label}\n summary={summarizeItem(component, item)}\n index={index}\n count={count}\n collapsed={collapsed}\n issueCount={issueCount}\n editable={editable}\n onToggle={() => onToggle(itemKey)}\n onMove={(to) => list.move(index, to)}\n onDuplicate={() => list.duplicate(index)}\n onRemove={() => list.remove(index)}\n >\n <ComponentItemFields component={component} item={item} onItemChange={onItemChange} path={itemPath} />\n </ItemCard>\n );\n};\n\n/**\n * The repeatable list as blocks of the entry canvas, with \"Add …\" at its end while it has room. Empty, it\n * says so in a row with the same button (and the minimum, when one item would not be enough), so the field\n * never collapses to a bare heading.\n */\nconst CanvasRepeatable = (props: BuiltInEditorProps & { component: ComponentDefinition }) => {\n const { t } = useTranslation();\n const { component, value, onChange, path, labelId, inputId, readOnly, disabled, definition, field } = props;\n const list = useListEditor(value, onChange);\n const settings = definition.type === 'component' ? definition.settings : undefined;\n const editable = !readOnly && !disabled;\n const room = hasRoomFor(list.items.length, settings?.max);\n const add = (variant: 'outline' | 'ghost') =>\n editable && room ? (\n <AddItemButton\n label={t('content.items.add', { item: component.label })}\n variant={variant}\n onClick={() => list.add(newComponentItem(component, false))}\n />\n ) : null;\n const empty = list.items.length === 0;\n // The list stays mounted while empty, so the first item added gets focus like any other.\n return (\n <div className=\"space-y-1\">\n {empty ? <EmptyListRow min={settings?.min} action={add('outline')} /> : null}\n <CanvasItemList\n list={list}\n labelId={labelId}\n inputId={inputId}\n path={path}\n editable={editable}\n insertable={room ? [component] : []}\n componentOf={() => component}\n newItem={(next) => newComponentItem(next, false)}\n startCollapsed={field.options.collapsed === true}\n />\n {empty ? null : add('ghost')}\n </div>\n );\n};\n\nconst Repeatable = (props: BuiltInEditorProps & { component: ComponentDefinition }) => {\n const { t } = useTranslation();\n const { component, value, onChange, path, labelId, inputId, readOnly, disabled, definition } = props;\n const list = useListEditor(value, onChange);\n const { collapsed, toggle } = useCollapsedItems(list.keys, props.field.options.collapsed === true);\n const domId = useCallback((key: string) => `${inputId}-item-${key}`, [inputId]);\n useFocusNewItem(list.keys, domId);\n const max = definition.type === 'component' ? definition.settings.max : undefined;\n const editable = !readOnly && !disabled;\n return (\n <div className=\"space-y-3\">\n {list.items.length > 0 ? (\n <ol aria-labelledby={labelId} className=\"space-y-2\">\n {list.items.map((item, index) => {\n const key = list.keys[index] ?? String(index);\n return (\n <RepeatableItem\n key={key}\n component={component}\n item={item}\n itemKey={key}\n index={index}\n count={list.items.length}\n path={path}\n domId={domId(key)}\n collapsed={collapsed.has(key)}\n editable={editable}\n list={list}\n onToggle={toggle}\n />\n );\n })}\n </ol>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.items.empty')}</p>\n )}\n {editable && hasRoomFor(list.items.length, max) ? (\n <AddItemButton\n label={t('content.items.add', { item: component.label })}\n onClick={() => list.add(newComponentItem(component, false))}\n />\n ) : null}\n </div>\n );\n};\n\nconst Single = (props: BuiltInEditorProps & { component: ComponentDefinition }) => {\n const { t } = useTranslation();\n const { component, value, onChange, path, readOnly, disabled, field } = props;\n const editable = !readOnly && !disabled;\n const onItemChange = useCallback((next: ItemValues) => onChange(next), [onChange]);\n if (!isRecord(value)) {\n return editable ? (\n <AddItemButton\n label={t('content.items.add', { item: component.label })}\n onClick={() => onChange(newComponentItem(component, false))}\n />\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.items.empty')}</p>\n );\n }\n return (\n <div className=\"space-y-4 rounded-xl border bg-card p-5\">\n <ComponentItemFields component={component} item={value} onItemChange={onItemChange} path={path} />\n {editable && !field.required ? (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => onChange(null)}>\n <Trash2 aria-hidden=\"true\" />\n {t('content.items.removeSingle', { item: component.label })}\n </Button>\n ) : null}\n </div>\n );\n};\n\n/** `componentEditor`: a reusable group of fields, once or as a repeatable list. */\nexport const ComponentField = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { components } = useFieldsEnvironment();\n const { definition } = props;\n const component =\n definition.type === 'component' ? components.get(definition.settings.component) : undefined;\n if (!component || definition.type !== 'component') {\n return <p className=\"text-sm text-destructive\">{t('content.items.componentMissing')}</p>;\n }\n if (definition.settings.repeatable && props.appearance === 'canvas') {\n return <CanvasRepeatable {...props} component={component} />;\n }\n return definition.settings.repeatable ? (\n <Repeatable {...props} component={component} />\n ) : (\n <Single {...props} component={component} />\n );\n};\n","import { X } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\n\ntype ClearButtonProps = { label: string; onClear: () => void; disabled?: boolean };\n\n/** Empties a field whose control has no empty state of its own (select, radio, date). */\nexport const ClearButton = ({ label, onClear, disabled }: ClearButtonProps) => {\n const { t } = useTranslation();\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n disabled={disabled}\n aria-label={t('content.fields.clearValue', { field: label })}\n onClick={onClear}\n >\n <X aria-hidden=\"true\" />\n </Button>\n );\n};\n","import { Input } from '@/components/ui/input';\nimport { ClearButton } from '../ClearButton';\nimport { inputAria, textValue } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `datePicker`: a calendar date stored as `YYYY-MM-DD`. */\nexport const DateInput = (props: BuiltInEditorProps) => {\n const { value, onChange, onBlur, readOnly, disabled, definition, field } = props;\n const settings = definition.type === 'date' ? definition.settings : {};\n const text = textValue(value);\n return (\n <div className=\"flex items-center gap-1\">\n <Input\n {...inputAria(props)}\n type=\"date\"\n value={text}\n min={settings.min}\n max={settings.max}\n readOnly={readOnly}\n disabled={disabled}\n className=\"w-auto\"\n onChange={(event) => onChange(event.target.value === '' ? null : event.target.value)}\n onBlur={onBlur}\n />\n {text && !readOnly ? (\n <ClearButton label={field.label} disabled={disabled} onClear={() => onChange(null)} />\n ) : null}\n </div>\n );\n};\n","/**\n * `datetime` values are canonical UTC ISO-8601 text (`2026-10-01T08:00:00.000Z`, ADR 0001). The browser's\n * `datetime-local` input works in wall-clock time without a zone, so values are converted both ways, in the\n * viewer's time zone (default) or in UTC (`display: 'utc'`).\n */\nconst pad = (value: number, length = 2) => String(value).padStart(length, '0');\n\nexport const toDateTimeInput = (iso: unknown, utc: boolean): string => {\n if (typeof iso !== 'string') {\n return '';\n }\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n const parts = utc\n ? [\n date.getUTCFullYear(),\n date.getUTCMonth() + 1,\n date.getUTCDate(),\n date.getUTCHours(),\n date.getUTCMinutes(),\n date.getUTCSeconds(),\n ]\n : [\n date.getFullYear(),\n date.getMonth() + 1,\n date.getDate(),\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n ];\n const [year = 0, month = 1, day = 1, hours = 0, minutes = 0, seconds = 0] = parts;\n return `${pad(year, 4)}-${pad(month)}-${pad(day)}T${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;\n};\n\n/** `2026-10-01T10:00` or `…T10:00:30` → canonical UTC text; null for empty or unreadable input. */\nexport const fromDateTimeInput = (text: string, utc: boolean): string | null => {\n if (text === '') {\n return null;\n }\n const withSeconds = /T\\d{2}:\\d{2}$/.test(text) ? `${text}:00` : text;\n const date = new Date(utc ? `${withSeconds}Z` : withSeconds);\n return Number.isNaN(date.getTime()) ? null : date.toISOString();\n};\n\n/** The viewer's IANA time zone, for the hint under local-time inputs. */\nexport const localTimeZone = (): string => Intl.DateTimeFormat().resolvedOptions().timeZone;\n","import { useTranslation } from 'react-i18next';\nimport { Input } from '@/components/ui/input';\nimport { ClearButton } from '../ClearButton';\nimport { fromDateTimeInput, localTimeZone, toDateTimeInput } from '../helpers/dates';\nimport { inputAria, stringOption } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `dateTimePicker`: a moment in time, edited in local time (or UTC) and stored as canonical UTC text. */\nexport const DateTimeInput = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { inputId, value, onChange, onBlur, readOnly, disabled, field } = props;\n const utc = stringOption(props, 'display') === 'utc';\n const hintId = `${inputId}-zone`;\n return (\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-1\">\n <Input\n {...inputAria(props, hintId)}\n type=\"datetime-local\"\n step={1}\n value={toDateTimeInput(value, utc)}\n readOnly={readOnly}\n disabled={disabled}\n className=\"w-auto\"\n onChange={(event) => onChange(fromDateTimeInput(event.target.value, utc))}\n onBlur={onBlur}\n />\n {value && !readOnly ? (\n <ClearButton label={field.label} disabled={disabled} onClear={() => onChange(null)} />\n ) : null}\n </div>\n <p id={hintId} className=\"text-meta text-muted-foreground\">\n {utc\n ? t('content.fields.dateTime.utc')\n : t('content.fields.dateTime.local', { zone: localTimeZone() })}\n </p>\n </div>\n );\n};\n","import type { ComponentDefinition, FieldDefinition } from '@shapio/schema';\nimport { useFieldsEnvironment } from '../form/context';\n\n/** Components that can be stored in a field: a zone's allowed ones, a component field's own (else none). */\nexport const allowedComponentsOf = (\n definition: FieldDefinition,\n components: ReadonlyMap<string, ComponentDefinition>,\n): ComponentDefinition[] => {\n const ids =\n definition.type === 'dynamiczone'\n ? definition.settings.components\n : definition.type === 'component'\n ? [definition.settings.component]\n : [];\n return ids\n .map((id) => components.get(id))\n .filter((component): component is ComponentDefinition => component !== undefined);\n};\n\nexport const useAllowedComponents = (definition: FieldDefinition) =>\n allowedComponentsOf(definition, useFieldsEnvironment().components);\n","import type { ComponentDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { AddItemButton } from '../../AddItemButton';\nimport { useDeferredMenuAction } from '../../hooks/useDeferredMenuAction';\n\ntype AddSectionMenuProps = {\n allowed: readonly ComponentDefinition[];\n onAdd: (component: ComponentDefinition) => void;\n};\n\n/** \"Add section\": a menu of the zone's allowed components. Adds after the menu closes, so focus can move. */\nexport const AddSectionMenu = ({ allowed, onAdd }: AddSectionMenuProps) => {\n const { t } = useTranslation();\n const menu = useDeferredMenuAction();\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <AddItemButton label={t('content.items.addSection')} />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" onCloseAutoFocus={menu.onCloseAutoFocus}>\n {allowed.map((component) => (\n <DropdownMenuItem key={component.id} onSelect={() => menu.defer(() => onAdd(component))}>\n {component.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n};\n","import type { ComponentDefinition } from '@shapio/schema';\nimport { ChevronsDownUp, ChevronsUpDown } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { CanvasItemList } from '../CanvasItemList';\nimport { ComponentItemFields } from '../ComponentItemFields';\nimport { EmptyListRow } from '../EmptyListRow';\nimport { newComponentItem } from '../helpers/formValues';\nimport { pointerOf } from '../helpers/issues';\nimport { hasRoomFor } from '../helpers/listLimits';\nimport { summarizeItem } from '../helpers/summary';\nimport { COMPONENT_KEY, type ItemValues } from '../helpers/values';\nimport { useAllowedComponents } from '../hooks/useAllowedComponents';\nimport { useCollapsedItems } from '../hooks/useCollapsedItems';\nimport { useFocusNewItem } from '../hooks/useFocusNewItem';\nimport { useItemIssueCount } from '../hooks/useItemIssueCount';\nimport { useListEditor } from '../hooks/useListEditor';\nimport { ItemCard } from '../ItemCard';\nimport type { BuiltInEditorProps } from '../types';\nimport { AddSectionMenu } from './AddSectionMenu';\n\ntype ZoneItemProps = {\n allowed: readonly ComponentDefinition[];\n item: ItemValues;\n itemKey: string;\n index: number;\n count: number;\n path: string;\n domId: string;\n collapsed: boolean;\n editable: boolean;\n list: ReturnType<typeof useListEditor>;\n onToggle: (key: string) => void;\n};\n\nconst ZoneItem = ({\n allowed,\n item,\n itemKey,\n index,\n count,\n path,\n domId,\n collapsed,\n editable,\n list,\n onToggle,\n}: ZoneItemProps) => {\n const { t } = useTranslation();\n const component = allowed.find((candidate) => candidate.apiKey === item[COMPONENT_KEY]);\n const itemPath = pointerOf(path, index);\n const issueCount = useItemIssueCount(itemPath);\n const onItemChange = useCallback((next: ItemValues) => list.update(index, next), [list, index]);\n return (\n <ItemCard\n id={domId}\n title={component?.label ?? t('content.items.unknownComponent', { key: String(item[COMPONENT_KEY]) })}\n summary={component ? summarizeItem(component, item) : ''}\n index={index}\n count={count}\n collapsed={collapsed}\n issueCount={issueCount}\n editable={editable}\n onToggle={() => onToggle(itemKey)}\n onMove={(to) => list.move(index, to)}\n onDuplicate={component ? () => list.duplicate(index) : undefined}\n onRemove={() => list.remove(index)}\n >\n {component ? (\n <ComponentItemFields component={component} item={item} onItemChange={onItemChange} path={itemPath} />\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.items.unknownComponentHint')}</p>\n )}\n </ItemCard>\n );\n};\n\n/**\n * The zone as blocks of the entry canvas. Empty, it says so in a row with \"Add section\" (and the minimum,\n * when one section would not be enough); the list stays mounted so the first section added gets focus.\n */\nconst CanvasZone = (props: BuiltInEditorProps) => {\n const { value, onChange, path, labelId, inputId, readOnly, disabled, definition, field } = props;\n const list = useListEditor(value, onChange);\n const allowed = useAllowedComponents(definition);\n const settings = definition.type === 'dynamiczone' ? definition.settings : undefined;\n const editable = !readOnly && !disabled;\n const room = hasRoomFor(list.items.length, settings?.max);\n return (\n <div>\n {list.items.length === 0 ? (\n <EmptyListRow\n min={settings?.min}\n action={\n editable && room && allowed.length > 0 ? (\n <AddSectionMenu\n allowed={allowed}\n onAdd={(component) => list.add(newComponentItem(component, true))}\n />\n ) : null\n }\n />\n ) : null}\n <CanvasItemList\n list={list}\n labelId={labelId}\n inputId={inputId}\n path={path}\n editable={editable}\n insertable={room ? allowed : []}\n componentOf={(item) => allowed.find((candidate) => candidate.apiKey === item[COMPONENT_KEY])}\n newItem={(component) => newComponentItem(component, true)}\n startCollapsed={field.options.collapsed === true}\n />\n </div>\n );\n};\n\n/**\n * `dynamicZoneEditor`: an ordered list of sections, each one of the zone's allowed components. Sections can\n * be added by type, reordered (buttons or Alt+↑/↓), duplicated, collapsed (with a readable summary) and\n * removed.\n */\nexport const DynamicZoneField = (props: BuiltInEditorProps) =>\n props.appearance === 'canvas' ? <CanvasZone {...props} /> : <FormZone {...props} />;\n\nconst FormZone = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { value, onChange, path, labelId, inputId, readOnly, disabled, definition, field } = props;\n const list = useListEditor(value, onChange);\n const { collapsed, toggle, setAll } = useCollapsedItems(list.keys, field.options.collapsed === true);\n const domId = useCallback((key: string) => `${inputId}-item-${key}`, [inputId]);\n useFocusNewItem(list.keys, domId);\n const allowed = useAllowedComponents(definition);\n const max = definition.type === 'dynamiczone' ? definition.settings.max : undefined;\n const editable = !readOnly && !disabled;\n const allCollapsed = list.keys.length > 0 && list.keys.every((key) => collapsed.has(key));\n return (\n <div className=\"space-y-3\">\n {list.items.length > 1 ? (\n <div className=\"flex justify-end\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => setAll(list.keys, !allCollapsed)}>\n {allCollapsed ? <ChevronsUpDown aria-hidden=\"true\" /> : <ChevronsDownUp aria-hidden=\"true\" />}\n {allCollapsed ? t('content.items.expandAll') : t('content.items.collapseAll')}\n </Button>\n </div>\n ) : null}\n {list.items.length > 0 ? (\n <ol aria-labelledby={labelId} className=\"space-y-2\">\n {list.items.map((item, index) => {\n const key = list.keys[index] ?? String(index);\n return (\n <ZoneItem\n key={key}\n allowed={allowed}\n item={item}\n itemKey={key}\n index={index}\n count={list.items.length}\n path={path}\n domId={domId(key)}\n collapsed={collapsed.has(key)}\n editable={editable}\n list={list}\n onToggle={toggle}\n />\n );\n })}\n </ol>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.items.emptyZone')}</p>\n )}\n {editable && hasRoomFor(list.items.length, max) ? (\n <AddSectionMenu\n allowed={allowed}\n onAdd={(component) => list.add(newComponentItem(component, true))}\n />\n ) : null}\n </div>\n );\n};\n","type ParseErrorProps = { id: string; message: string | undefined };\n\n/** An editor's own \"this text can't be read\" message (the value is not sent until it parses). */\nexport const ParseError = ({ id, message }: ParseErrorProps) =>\n message ? (\n <p id={id} role=\"alert\" className=\"text-sm text-destructive\">\n {message}\n </p>\n ) : null;\n","import { Braces } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Textarea } from '@/components/ui/textarea';\nimport { inputAria, numberOption } from '../helpers/props';\nimport { isDeepEqual } from '../helpers/values';\nimport { ParseError } from '../ParseError';\nimport type { BuiltInEditorProps } from '../types';\n\nconst DEFAULT_ROWS = 8;\nconst INDENT = 2;\n\nconst format = (value: unknown) =>\n value === null || value === undefined ? '' : JSON.stringify(value, null, INDENT);\n\nconst parse = (text: string): { ok: true; value: unknown } | { ok: false; message: string } => {\n if (text.trim() === '') {\n return { ok: true, value: null };\n }\n try {\n return { ok: true, value: JSON.parse(text) as unknown };\n } catch (error) {\n return { ok: false, message: error instanceof Error ? error.message : String(error) };\n }\n};\n\n/** `jsonEditor`: any JSON value, as text. Only text that parses becomes the value; errors show inline. */\nexport const JsonEditor = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { inputId, value, onChange, onBlur, readOnly, disabled } = props;\n const [text, setText] = useState(() => format(value));\n const [problem, setProblem] = useState<string | undefined>();\n const [seen, setSeen] = useState(value);\n // Follow outside changes (reload, restore, copy from another locale) unless they match what's typed.\n if (!Object.is(seen, value)) {\n setSeen(value);\n const parsed = parse(text);\n if (!parsed.ok || !isDeepEqual(parsed.value, value ?? null)) {\n setText(format(value));\n setProblem(undefined);\n }\n }\n const errorId = `${inputId}-parse`;\n return (\n <div className=\"space-y-1\">\n <Textarea\n {...inputAria(props, problem ? errorId : undefined)}\n aria-invalid={props.validation.invalid || problem !== undefined || undefined}\n rows={numberOption(props, 'rows') ?? DEFAULT_ROWS}\n value={text}\n spellCheck={false}\n readOnly={readOnly}\n disabled={disabled}\n className=\"font-mono text-sm\"\n onChange={(event) => {\n setText(event.target.value);\n const parsed = parse(event.target.value);\n setProblem(parsed.ok ? undefined : parsed.message);\n if (parsed.ok) {\n onChange(parsed.value);\n }\n }}\n onBlur={onBlur}\n />\n <div className=\"flex items-start justify-between gap-2\">\n <ParseError\n id={errorId}\n message={problem ? t('content.fields.json.invalid', { reason: problem }) : undefined}\n />\n {!readOnly ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n disabled={disabled || problem !== undefined || text.trim() === ''}\n onClick={() => setText(format(value))}\n >\n <Braces aria-hidden=\"true\" />\n {t('content.fields.json.format')}\n </Button>\n ) : null}\n </div>\n </div>\n );\n};\n","import { ArrowLeft, ArrowRight, ImageOff, Trash2 } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useMediaAsset } from '@/api/media';\nimport { Button } from '@/components/ui/button';\nimport { Skeleton } from '@/components/ui/skeleton';\nimport { Thumbnail } from '@/features/Media/Thumbnail';\n\ntype GalleryTileProps = {\n assetId: string;\n index: number;\n count: number;\n editable: boolean;\n onMove: (to: number) => void;\n onRemove: () => void;\n};\n\n/** One file of a canvas gallery: its thumbnail and name, with move and remove on hover or focus. */\nexport const GalleryTile = ({ assetId, index, count, editable, onMove, onRemove }: GalleryTileProps) => {\n const { t } = useTranslation();\n const asset = useMediaAsset(assetId);\n const name = asset.data?.filename ?? assetId;\n return (\n <li className=\"group/tile relative space-y-1.5\">\n {asset.data ? (\n <Thumbnail asset={asset.data} className=\"aspect-square w-full rounded-xl\" />\n ) : asset.isPending ? (\n <Skeleton className=\"aspect-square w-full rounded-xl\" />\n ) : (\n <div className=\"flex aspect-square w-full items-center justify-center rounded-xl bg-muted text-muted-foreground\">\n <ImageOff aria-hidden=\"true\" className=\"size-5\" />\n </div>\n )}\n <p className=\"truncate text-meta text-muted-foreground\">\n {asset.isError ? t('content.media.missing') : name}\n </p>\n {editable ? (\n <div className=\"absolute top-2 right-2 flex gap-1 rounded-lg bg-popover p-0.5 opacity-0 shadow-sm transition-opacity group-focus-within/tile:opacity-100 group-hover/tile:opacity-100\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={t('content.items.moveUp', { item: name, position: index + 1 })}\n disabled={index === 0}\n onClick={() => onMove(index - 1)}\n >\n <ArrowLeft aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={t('content.items.moveDown', { item: name, position: index + 1 })}\n disabled={index === count - 1}\n onClick={() => onMove(index + 1)}\n >\n <ArrowRight aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={t('content.media.remove', { name })}\n onClick={onRemove}\n >\n <Trash2 aria-hidden=\"true\" />\n </Button>\n </div>\n ) : null}\n </li>\n );\n};\n","import { ImagePlus } from 'lucide-react';\nimport { useState, type DragEvent } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { cn } from '@/helpers/cn';\nimport { logError } from '@/helpers/reportError';\nimport { useFieldsEnvironment } from '../../form/context';\nimport { moveItem } from '../../helpers/values';\nimport { GalleryTile } from '../GalleryTile';\n\ntype GalleryProps = {\n ids: readonly string[];\n labelId: string;\n inputId: string;\n editable: boolean;\n /** More files fit (under the field's `max`). */\n canAdd: boolean;\n onPick: () => void;\n commit: (ids: string[]) => void;\n};\n\n/**\n * Several files as a gallery block of the canvas: thumbnails in a grid, a tile to add more from the\n * library, and files dropped onto it uploaded straight in (with `media.write`).\n */\nexport const Gallery = ({ ids, labelId, inputId, editable, canAdd, onPick, commit }: GalleryProps) => {\n const { t } = useTranslation();\n const { uploadMedia } = useFieldsEnvironment();\n const [dropping, setDropping] = useState(false);\n const [uploading, setUploading] = useState(0);\n const acceptsFiles = editable && canAdd && uploadMedia !== undefined;\n const onDrop = async (event: DragEvent) => {\n setDropping(false);\n const files = [...event.dataTransfer.files];\n if (!acceptsFiles || files.length === 0 || !uploadMedia) {\n return;\n }\n event.preventDefault();\n setUploading((count) => count + files.length);\n const added: string[] = [];\n for (const file of files) {\n try {\n added.push((await uploadMedia(file)).id);\n } catch (error) {\n logError(error, `uploading ${file.name} into a gallery`);\n toast.error(t('entry.upload.failed', { name: file.name }));\n } finally {\n setUploading((count) => count - 1);\n }\n }\n if (added.length > 0) {\n commit([...ids, ...added]);\n }\n };\n return (\n <div\n className={cn('rounded-xl font-sans', dropping && 'ring-[3px] ring-ring/50')}\n onDragOver={(event) => {\n if (acceptsFiles && event.dataTransfer.types.includes('Files')) {\n event.preventDefault();\n setDropping(true);\n }\n }}\n onDragLeave={() => setDropping(false)}\n onDrop={(event) => void onDrop(event)}\n >\n <ul aria-labelledby={labelId} className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n {ids.map((id, index) => (\n <GalleryTile\n key={id}\n assetId={id}\n index={index}\n count={ids.length}\n editable={editable}\n onMove={(to) => commit(moveItem(ids, index, to))}\n onRemove={() => commit(ids.filter((item) => item !== id))}\n />\n ))}\n </ul>\n {editable && canAdd ? (\n <button\n id={inputId}\n type=\"button\"\n onClick={onPick}\n className={cn(\n 'mt-3 flex h-20 w-full items-center justify-center gap-2 rounded-xl border border-dashed text-sm text-muted-foreground outline-none hover:bg-muted/50 hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50',\n )}\n >\n <ImagePlus aria-hidden=\"true\" className=\"size-4\" />\n {uploading > 0\n ? t('entry.upload.uploadingCount', { count: uploading })\n : uploadMedia\n ? t('entry.gallery.addOrDrop')\n : t('content.media.add')}\n </button>\n ) : null}\n </div>\n );\n};\n","import { ImagePlus } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { reportError } from '@/helpers/reportError';\nimport { useMediaPermissions } from '@/hooks/useMediaPermissions';\nimport { moveItem, toList } from '../helpers/values';\nimport type { BuiltInEditorProps } from '../types';\nimport { AssetTile } from './AssetTile';\nimport { Gallery } from './Gallery';\n\n/**\n * `mediaPicker`: one or several files from the media library (chosen in a sheet, uploads included).\n * The value is asset IDs; previews, alt text and variants come from the library.\n */\nexport const MediaField = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { canWrite } = useMediaPermissions();\n const { value, onChange, onBlur, readOnly, disabled, definition, context, inputId, labelId, describedBy } =\n props;\n const settings = definition.type === 'media' ? definition.settings : { multiple: false };\n const multiple = settings.multiple;\n const ids = toList<string>(value).filter((id): id is string => typeof id === 'string');\n const editable = !readOnly && !disabled;\n const commit = (next: string[]) => {\n onChange(multiple ? (next.length > 0 ? next : null) : (next[0] ?? null));\n onBlur();\n };\n const pick = async () => {\n try {\n const picked = await context.pickMedia({\n multiple,\n ...('allowedKinds' in settings && settings.allowedKinds\n ? { allowedKinds: settings.allowedKinds }\n : {}),\n });\n if (picked && picked.length > 0) {\n const chosen = picked.map((asset) => asset.id);\n commit(multiple ? [...ids, ...chosen.filter((id) => !ids.includes(id))] : chosen.slice(0, 1));\n }\n } catch (error) {\n reportError(error, 'picking media');\n }\n };\n const max = 'max' in settings ? settings.max : undefined;\n if (multiple && props.appearance === 'canvas') {\n return (\n <Gallery\n ids={ids}\n labelId={labelId}\n inputId={inputId}\n editable={editable}\n canAdd={max === undefined || ids.length < max}\n onPick={() => void pick()}\n commit={commit}\n />\n );\n }\n return (\n <div role=\"group\" aria-labelledby={labelId} aria-describedby={describedBy} className=\"space-y-2\">\n {ids.length > 0 ? (\n <ul className=\"space-y-2\">\n {ids.map((id, index) => (\n <AssetTile\n key={id}\n assetId={id}\n inputId={inputId}\n index={index}\n count={ids.length}\n editable={editable}\n canEditAlt={canWrite && !readOnly}\n onMove={multiple ? (to) => commit(moveItem(ids, index, to)) : undefined}\n onRemove={() => commit(ids.filter((item) => item !== id))}\n />\n ))}\n </ul>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.media.empty')}</p>\n )}\n {editable && (multiple ? max === undefined || ids.length < max : true) ? (\n <Button id={inputId} type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void pick()}>\n <ImagePlus aria-hidden=\"true\" />\n {multiple\n ? t('content.media.add')\n : ids.length > 0\n ? t('content.media.replace')\n : t('content.media.chooseOne')}\n </Button>\n ) : null}\n </div>\n );\n};\n","import { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Input } from '@/components/ui/input';\nimport { inputAria, numberOption, stringOption, textValue } from '../helpers/props';\nimport { ParseError } from '../ParseError';\nimport type { BuiltInEditorProps } from '../types';\n\nconst INTEGER = /^-?\\d+$/;\nconst NUMBER = /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][-+]?\\d+)?$/;\n\n/** Text → value: numbers for `number`/`integer`, canonical strings for `decimal`/`biginteger`. */\nconst parse = (type: string, text: string): { ok: true; value: number | string | null } | { ok: false } => {\n const trimmed = text.trim();\n if (trimmed === '') {\n return { ok: true, value: null };\n }\n if (type === 'decimal' || type === 'biginteger') {\n // Kept as typed: the format check (and the server) report anything that is not a canonical number.\n return { ok: true, value: trimmed };\n }\n if (!(type === 'integer' ? INTEGER : NUMBER).test(trimmed)) {\n return { ok: false };\n }\n const number = Number(trimmed);\n return Number.isFinite(number) && (type !== 'integer' || Number.isSafeInteger(number))\n ? { ok: true, value: number }\n : { ok: false };\n};\n\n/**\n * `numberInput`: number, integer, decimal and big integer. Typed as text so partial input (\"1.\", \"-\")\n * isn't lost; only text that parses is reported as the value.\n */\nexport const NumberInput = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { inputId, value, onChange, onBlur, readOnly, disabled, definition } = props;\n const [text, setText] = useState(() => textValue(value));\n const [invalid, setInvalid] = useState(false);\n const [seen, setSeen] = useState(value);\n // Follow outside changes (reload, restore, copy from another locale) unless they match what's typed.\n if (!Object.is(seen, value)) {\n setSeen(value);\n const parsed = parse(definition.type, text);\n if (!parsed.ok || parsed.value !== value) {\n setText(textValue(value));\n setInvalid(false);\n }\n }\n const parseErrorId = `${inputId}-parse`;\n const integer = definition.type === 'integer' || definition.type === 'biginteger';\n return (\n <div className=\"space-y-1\">\n <Input\n {...inputAria(props, invalid ? parseErrorId : undefined)}\n aria-invalid={props.validation.invalid || invalid || undefined}\n inputMode={integer ? 'numeric' : 'decimal'}\n value={text}\n placeholder={stringOption(props, 'placeholder')}\n step={numberOption(props, 'step')}\n readOnly={readOnly}\n disabled={disabled}\n className=\"tabular-nums\"\n onChange={(event) => {\n setText(event.target.value);\n const parsed = parse(definition.type, event.target.value);\n setInvalid(!parsed.ok);\n if (parsed.ok) {\n onChange(parsed.value);\n }\n }}\n onBlur={onBlur}\n />\n <ParseError\n id={parseErrorId}\n message={\n invalid\n ? t(integer ? 'content.fields.number.notInteger' : 'content.fields.number.notNumber')\n : undefined\n }\n />\n </div>\n );\n};\n","import { Label } from '@/components/ui/label';\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';\nimport { cn } from '@/helpers/cn';\nimport { ClearButton } from '../ClearButton';\nimport { choicesOf, fromChoice, toChoice } from '../helpers/choices';\nimport { stringOption } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `radio`: radio buttons for a single-choice enum, vertical or horizontal. */\nexport const RadioInput = (props: BuiltInEditorProps) => {\n const { inputId, labelId, describedBy, value, onChange, onBlur, readOnly, disabled, field, validation } =\n props;\n const current = toChoice(value);\n const horizontal = stringOption(props, 'layout') === 'horizontal';\n return (\n <div className=\"flex items-start gap-2\">\n <RadioGroup\n aria-labelledby={labelId}\n aria-describedby={describedBy}\n aria-invalid={validation.invalid || undefined}\n value={current}\n disabled={disabled || readOnly}\n onValueChange={(choice) => onChange(fromChoice(props, choice))}\n onBlur={onBlur}\n className={cn(horizontal && 'flex flex-wrap gap-x-6')}\n >\n {choicesOf(props).map((choice) => (\n <div key={choice.value} className=\"flex items-center gap-2\">\n <RadioGroupItem id={`${inputId}-${choice.value}`} value={choice.value} />\n <Label htmlFor={`${inputId}-${choice.value}`} className=\"font-normal\">\n {choice.label}\n </Label>\n </div>\n ))}\n </RadioGroup>\n {current && !field.required && !readOnly ? (\n <ClearButton label={field.label} disabled={disabled} onClear={() => onChange(null)} />\n ) : null}\n </div>\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useMemo } from 'react';\nimport { useEntryList } from '@/api/content';\nimport { titleFieldOf } from '../helpers/titles';\n\nconst MAX_LOOKUP = 100;\n\n/** Titles of related entries by ID, read in one list request (`filters[id][$in]`). */\nexport const useEntryLabels = (\n model: ModelDefinition | undefined,\n ids: readonly string[],\n locale: string | null,\n) => {\n const title = model ? titleFieldOf(model) : undefined;\n const lookup = ids.slice(0, MAX_LOOKUP);\n const query = {\n filters: { id: { $in: [...lookup].sort() } },\n pageSize: Math.max(lookup.length, 1),\n ...(title ? { fields: [title.apiKey] } : {}),\n ...(locale && model?.localized ? { locale } : {}),\n };\n const list = useEntryList(model?.apiKey ?? '', query, model !== undefined && lookup.length > 0);\n const items = list.data?.items;\n const byId = useMemo(() => new Map((items ?? []).map((item) => [item.id, item])), [items]);\n return { byId, isLoading: list.isPending && lookup.length > 0, error: list.error };\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport { memo } from 'react';\nimport { FieldControl, type FieldLayout } from '../../FieldControl';\nimport { useTopLevelValue } from '../../hooks/useTopLevelValue';\nimport { useFieldsEnvironment } from '../context';\n\ntype TopLevelFieldProps = {\n field: FieldDefinition;\n layout?: FieldLayout;\n className?: string;\n};\n\n/** A field of the entry itself, as a labelled control: subscribes to its own value only. */\nexport const TopLevelField = memo(({ field, layout, className }: TopLevelFieldProps) => {\n const { model } = useFieldsEnvironment();\n const { value, onChange } = useTopLevelValue(field);\n return (\n <FieldControl\n field={field}\n owner={model}\n value={value}\n onChange={onChange}\n path={`/${field.apiKey}`}\n topLevel\n layout={layout}\n className={className}\n />\n );\n});\n\nTopLevelField.displayName = 'TopLevelField';\n","import type { FieldDefinition } from '@shapio/schema';\nimport { FieldGrid } from '../../FieldGrid';\nimport type { FieldGridMode } from '../../helpers/widthClasses';\nimport { EntrySiblings } from '../EntrySiblings';\nimport { TopLevelField } from '../TopLevelField';\n\ntype EntryFieldsProps = {\n fields: readonly FieldDefinition[];\n /** `widths` for a form-layout entry (each field at its `width`); quick edit keeps the compact split. */\n mode?: FieldGridMode;\n};\n\n/** The entry's own fields (one section of the form). */\nexport const EntryFields = ({ fields, mode }: EntryFieldsProps) => (\n <EntrySiblings>\n <FieldGrid\n fields={fields}\n mode={mode}\n renderField={(field, className) => (\n <TopLevelField key={field.id} field={field} layout=\"stacked\" className={className} />\n )}\n />\n </EntrySiblings>\n);\n","import type { ContentIssue } from '@shapio/client';\nimport { createStore } from 'zustand/vanilla';\nimport { dirtyKeysOf, mergeSaved } from '../helpers/formValues';\nimport type { FormValues } from '../helpers/values';\n\n/**\n * State of one entry form: the values being edited, the baseline they are compared with (what the server\n * last returned), and validation issues. One store per open form (the page's form and an inline-create\n * drawer each have their own), so fields subscribe to just their own value.\n */\nexport type EntryFormState = {\n values: FormValues;\n baseline: FormValues;\n /** Server issues from the last save, plus none of the client-side checks (computed per field). */\n issues: readonly ContentIssue[];\n /** Paths whose client-side checks are shown (after the field was left, or after a save attempt). */\n touched: ReadonlySet<string>;\n /** Show every field's client-side issues (set by a save or publish attempt). */\n revealAll: boolean;\n setValue: (apiKey: string, value: unknown) => void;\n /** Replaces several values at once (copy from another locale, reload keeping local edits). */\n patchValues: (values: FormValues) => void;\n touch: (path: string) => void;\n reveal: () => void;\n setIssues: (issues: readonly ContentIssue[]) => void;\n /** Starts over from values loaded from the server. */\n load: (values: FormValues) => void;\n /** Rebases onto newly loaded values, keeping these local changes on top. */\n rebase: (values: FormValues, local: FormValues) => void;\n /** Accepts a save's result; see `mergeSaved`. */\n acceptSaved: (sent: FormValues, saved: FormValues) => void;\n};\n\nexport type EntryFormStore = ReturnType<typeof createEntryFormStore>;\n\nconst withoutIssuesUnder = (issues: readonly ContentIssue[], apiKey: string) => {\n const prefix = `/${apiKey}`;\n return issues.filter((issue) => issue.path !== prefix && !issue.path.startsWith(`${prefix}/`));\n};\n\nexport const createEntryFormStore = (initial: FormValues) =>\n createStore<EntryFormState>()((set) => ({\n values: initial,\n baseline: initial,\n issues: [],\n touched: new Set(),\n revealAll: false,\n setValue: (apiKey, value) =>\n set((state) => ({\n values: { ...state.values, [apiKey]: value },\n // A changed value makes the server's verdict on it stale.\n issues: withoutIssuesUnder(state.issues, apiKey),\n })),\n patchValues: (values) =>\n set((state) => ({\n values: { ...state.values, ...values },\n issues: Object.keys(values).reduce(withoutIssuesUnder, state.issues),\n })),\n touch: (path) =>\n set((state) => (state.touched.has(path) ? state : { touched: new Set([...state.touched, path]) })),\n reveal: () => set({ revealAll: true }),\n setIssues: (issues) => set({ issues }),\n load: (values) => set({ values, baseline: values, issues: [], touched: new Set(), revealAll: false }),\n rebase: (values, local) => set({ values: { ...values, ...local }, baseline: values, issues: [] }),\n acceptSaved: (sent, saved) => set((state) => mergeSaved(state.values, sent, saved)),\n }));\n\n/** Top-level API keys with unsaved changes. */\nexport const selectDirtyKeys = (state: Pick<EntryFormState, 'values' | 'baseline'>) =>\n dirtyKeysOf(state.values, state.baseline);\n","import { ShapioApiError, type ContentIssue, type EntryReferrer } from '@shapio/client';\nimport { isRecord } from './values';\n\n/** The issues of a 422 CONTENT_INVALID answer (empty for any other error). */\nexport const contentIssuesOf = (error: unknown): ContentIssue[] => {\n if (!(error instanceof ShapioApiError) || error.code !== 'CONTENT_INVALID' || !isRecord(error.details)) {\n return [];\n }\n const issues = error.details.issues;\n return Array.isArray(issues)\n ? issues.filter(\n (issue): issue is ContentIssue =>\n isRecord(issue) && typeof issue.path === 'string' && typeof issue.code === 'string',\n )\n : [];\n};\n\n/** The entries still pointing at one being deleted (409 ENTRY_REFERENCED). */\nexport const referrersOf = (error: unknown): EntryReferrer[] => {\n if (!(error instanceof ShapioApiError) || error.code !== 'ENTRY_REFERENCED' || !isRecord(error.details)) {\n return [];\n }\n const referrers = error.details.referrers;\n return Array.isArray(referrers) ? referrers.filter((item): item is EntryReferrer => isRecord(item)) : [];\n};\n\n/** A save that lost a race: the draft moved (another session) or the model changed while saving. */\nexport const isEditConflict = (error: unknown): error is ShapioApiError =>\n error instanceof ShapioApiError &&\n error.status === 409 &&\n (error.code === 'CONTENT_VERSION_CONFLICT' || error.code === 'SCHEMA_CHANGED');\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useStore } from 'zustand';\nimport { useCreateEntry } from '@/api/content';\nimport { FormError } from '@/components/FormError';\nimport { SubmitButton } from '@/components/SubmitButton';\nimport { Button } from '@/components/ui/button';\nimport { Sheet, SheetBody, SheetContent, SheetFooter, SheetHeader, SheetTitle } from '@/components/ui/sheet';\nimport { useDiscardGuard } from '@/hooks/useDiscardGuard';\nimport { useFieldsEnvironment } from '../../form/context';\nimport { EntryFields } from '../../form/EntryFields';\nimport { FieldsProvider } from '../../form/FieldsProvider';\nimport { createEntryFormStore, selectDirtyKeys } from '../../form/store';\nimport { contentIssuesOf } from '../../helpers/apiErrors';\nimport { buildCreateData, defaultFormValues, liveFields } from '../../helpers/formValues';\nimport { fieldGridModeOf } from '../../helpers/widthClasses';\n\ntype InlineCreateSheetProps = {\n target: ModelDefinition;\n onClose: () => void;\n onCreated: (id: string) => void;\n};\n\n/**\n * Creates an entry of a relation's target model without leaving the form (the relation editor's\n * `allowInlineCreate` option). The server checks the create permission; a refusal shows here.\n */\nexport const InlineCreateSheet = ({ target, onClose, onCreated }: InlineCreateSheetProps) => {\n const { t } = useTranslation();\n const outer = useFieldsEnvironment();\n const [store] = useState(() => createEntryFormStore(defaultFormValues(target.fields)));\n const dirty = useStore(store, (state) => selectDirtyKeys(state).length > 0);\n const create = useCreateEntry(target.apiKey);\n const { requestOpenChange, discardPrompt } = useDiscardGuard({\n dirty,\n pending: create.isPending,\n onOpenChange: (open) => (open ? undefined : onClose()),\n });\n const locale = target.localized ? outer.locale : null;\n const environment = useMemo(\n () => ({\n ...outer,\n idPrefix: `${outer.idPrefix}inline-`,\n model: target,\n locale,\n entryId: null,\n readOnly: false,\n disabled: create.isPending,\n }),\n [outer, target, locale, create.isPending],\n );\n const submit = async () => {\n store.getState().reveal();\n try {\n const entry = await create.mutateAsync({\n ...(locale ? { locale } : {}),\n data: buildCreateData(store.getState().values),\n });\n onCreated(entry.id);\n } catch (error) {\n // Logged by the mutation cache; issues show on the fields, anything else above the buttons.\n store.getState().setIssues(contentIssuesOf(error));\n }\n };\n const issues = contentIssuesOf(create.error);\n return (\n <>\n <Sheet open onOpenChange={requestOpenChange}>\n <SheetContent size=\"md\" aria-describedby={undefined}>\n <SheetHeader>\n <SheetTitle>{t('content.relation.createTitle', { model: target.label })}</SheetTitle>\n </SheetHeader>\n <form\n noValidate\n className=\"flex min-h-0 flex-1 flex-col\"\n onSubmit={(event) => {\n event.preventDefault();\n void submit();\n }}\n >\n <SheetBody className=\"space-y-5\">\n <FieldsProvider environment={environment} store={store}>\n <EntryFields fields={liveFields(target.fields)} mode={fieldGridModeOf(target)} />\n </FieldsProvider>\n {create.isError && issues.length === 0 ? <FormError error={create.error} /> : null}\n {issues.length > 0 ? (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {t('content.form.fixProblems', { count: issues.length })}\n </p>\n ) : null}\n </SheetBody>\n <SheetFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => requestOpenChange(false)}>\n {t('common.cancel')}\n </Button>\n <SubmitButton pending={create.isPending} pendingLabel={t('content.form.creating')}>\n {t('content.relation.createAndLink')}\n </SubmitButton>\n </SheetFooter>\n </form>\n </SheetContent>\n </Sheet>\n {discardPrompt}\n </>\n );\n};\n","import { useSyncExternalStore } from 'react';\n\n// Tailwind's `md` breakpoint (48rem).\nconst MD_QUERY = '(min-width: 48rem)';\n\nconst subscribe = (onChange: () => void) => {\n const query = window.matchMedia(MD_QUERY);\n query.addEventListener('change', onChange);\n return () => query.removeEventListener('change', onChange);\n};\n\nconst getSnapshot = () => window.matchMedia(MD_QUERY).matches;\n\n/** True from the `md` breakpoint up: pickers anchor a popover to their field there, and use a bottom sheet below. */\nexport const useIsMdUp = () => useSyncExternalStore(subscribe, getSnapshot, () => true);\n","import { useState } from 'react';\n\n/**\n * The highlighted option of a listbox driven by `aria-activedescendant` (focus stays on the combobox).\n * Remembered by id, so it survives new results and clears itself when its option goes away.\n */\nexport const useActiveOption = (ids: readonly string[]) => {\n const [rememberedId, setActiveId] = useState<string | undefined>();\n const activeId = rememberedId !== undefined && ids.includes(rememberedId) ? rememberedId : undefined;\n /** ↓ from nothing goes to the first option, ↑ to the last; both stop at the ends. */\n const move = (delta: 1 | -1) => {\n if (ids.length === 0) {\n return;\n }\n const index = activeId === undefined ? -1 : ids.indexOf(activeId);\n const next = index === -1 ? (delta === 1 ? 0 : ids.length - 1) : index + delta;\n setActiveId(ids[Math.min(Math.max(next, 0), ids.length - 1)]);\n };\n return {\n activeId,\n setActiveId,\n move,\n first: () => setActiveId(ids[0]),\n last: () => setActiveId(ids.at(-1)),\n };\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { Check, Search } from 'lucide-react';\nimport { useEffect, useId, useState, type KeyboardEvent } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useEntryList } from '@/api/content';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { Input } from '@/components/ui/input';\nimport { cn } from '@/helpers/cn';\nimport { useDebouncedValue } from '@/hooks/useDebouncedValue';\nimport { isSearchable, labelOf } from '../../../helpers/titles';\nimport { useActiveOption } from '../hooks/useActiveOption';\n\nconst PAGE_SIZE = 20;\nconst SEARCH_DEBOUNCE_MS = 300;\n\ntype ResultsProps = {\n target: ModelDefinition;\n locale: string | null;\n multiple: boolean;\n /** Linked now: shown as selected. */\n selected: readonly string[];\n /** Never offered (the entry being edited, for self-relations). */\n exclude: readonly string[];\n /** No more may be linked (relation `max`): unselected options are disabled. */\n full: boolean;\n onPick: (id: string) => void;\n onUnpick: (id: string) => void;\n className?: string;\n /** Sizing of the scrolling result list (the popover caps it; the sheet lets it grow). */\n listClassName?: string;\n};\n\n/**\n * The relation picker's body: a combobox search over the target's titles (when it has a searchable title)\n * and the matching entries as a listbox. Focus stays in the search box; ↑/↓ move the highlighted option\n * (`aria-activedescendant`) and Enter picks it. Without a search box the listbox itself takes focus.\n */\nexport const Results = ({\n target,\n locale,\n multiple,\n selected,\n exclude,\n full,\n onPick,\n onUnpick,\n className,\n listClassName,\n}: ResultsProps) => {\n const { t } = useTranslation();\n const listboxId = useId();\n const [text, setText] = useState('');\n const q = useDebouncedValue(text.trim(), SEARCH_DEBOUNCE_MS);\n const searchable = isSearchable(target);\n const list = useEntryList(target.apiKey, {\n pageSize: PAGE_SIZE,\n ...(q && searchable ? { q } : {}),\n ...(locale && target.localized ? { locale } : {}),\n });\n const items = (list.data?.items ?? []).filter((item) => !exclude.includes(item.id));\n const active = useActiveOption(items.map((item) => item.id));\n const optionId = (id: string) => `${listboxId}-${id}`;\n const activeDescendant = active.activeId ? optionId(active.activeId) : undefined;\n\n useEffect(() => {\n if (activeDescendant) {\n document.getElementById(activeDescendant)?.scrollIntoView({ block: 'nearest' });\n }\n }, [activeDescendant]);\n\n const choose = (id: string) => {\n const isSelected = selected.includes(id);\n if (multiple && isSelected) {\n onUnpick(id);\n } else if (!(multiple && full)) {\n onPick(id);\n }\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLElement>) => {\n if (event.altKey || event.ctrlKey || event.metaKey) {\n return;\n }\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n active.move(event.key === 'ArrowDown' ? 1 : -1);\n } else if ((event.key === 'Home' || event.key === 'End') && !searchable) {\n // In the search box Home/End move the caret.\n event.preventDefault();\n if (event.key === 'Home') {\n active.first();\n } else {\n active.last();\n }\n } else if (event.key === 'Enter' && active.activeId) {\n event.preventDefault();\n choose(active.activeId);\n }\n };\n\n return (\n <div className={cn('flex min-h-0 flex-col gap-3', className)}>\n {searchable ? (\n <div className=\"relative\">\n <Search\n aria-hidden=\"true\"\n className=\"absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n type=\"search\"\n role=\"combobox\"\n aria-expanded=\"true\"\n aria-controls={listboxId}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeDescendant}\n value={text}\n aria-label={t('content.relation.search', { model: target.label })}\n placeholder={t('content.relation.searchPlaceholder')}\n className=\"pl-9\"\n onChange={(event) => setText(event.target.value)}\n onKeyDown={onKeyDown}\n />\n </div>\n ) : null}\n <ul\n id={listboxId}\n role=\"listbox\"\n aria-label={t('content.relation.results')}\n aria-multiselectable={multiple || undefined}\n aria-busy={list.isPending || undefined}\n aria-activedescendant={searchable ? undefined : activeDescendant}\n tabIndex={searchable ? undefined : 0}\n onKeyDown={searchable ? undefined : onKeyDown}\n className={cn(\n 'min-h-0 space-y-0.5 overflow-y-auto rounded-lg outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n listClassName,\n )}\n >\n {items.map((item) => {\n const isSelected = selected.includes(item.id);\n const disabled = multiple && full && !isSelected;\n return (\n <li\n key={item.id}\n id={optionId(item.id)}\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={disabled || undefined}\n data-active={item.id === active.activeId || undefined}\n className={cn(\n 'flex cursor-pointer items-center gap-2 rounded-md px-2 py-2 text-sm select-none data-[active]:bg-accent data-[active]:text-accent-foreground',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n // Focus stays in the search box (or on the listbox) while options are clicked.\n onMouseDown={(event) => event.preventDefault()}\n onPointerMove={() => (item.id === active.activeId ? undefined : active.setActiveId(item.id))}\n onClick={() => choose(item.id)}\n >\n <Check aria-hidden=\"true\" className={cn('size-4 shrink-0', !isSelected && 'invisible')} />\n <span className=\"min-w-0 truncate\">{labelOf(target, item, t('content.untitled'))}</span>\n </li>\n );\n })}\n </ul>\n {list.isPending ? (\n <LoadingState rows={3} />\n ) : list.isError ? (\n <ErrorState error={list.error} onRetry={() => void list.refetch()} />\n ) : items.length === 0 ? (\n <p role=\"status\" className=\"py-4 text-center text-sm text-muted-foreground\">\n {t('content.relation.noResults')}\n </p>\n ) : null}\n </div>\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { Plus } from 'lucide-react';\nimport { useId, useRef, type ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport {\n Sheet,\n SheetBody,\n SheetContent,\n SheetFooter,\n SheetHeader,\n SheetTitle,\n SheetTrigger,\n} from '@/components/ui/sheet';\nimport { useIsMdUp } from '../../hooks/useIsMdUp';\nimport { Results } from './Results';\n\ntype RelationPickerProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** The field's button that opens the picker; absent while nothing more can be linked. */\n trigger: ReactElement | null;\n target: ModelDefinition;\n multiple: boolean;\n /** Linked now. */\n selected: readonly string[];\n /** Never offered (the entry being edited, for self-relations). */\n exclude: readonly string[];\n locale: string | null;\n /** No more may be linked (relation `max`). */\n full: boolean;\n canCreate: boolean;\n /** Links an entry: in single mode the picker then closes, in multi mode it stays open for more. */\n onPick: (id: string) => void;\n onUnpick: (id: string) => void;\n /** Runs once the picker has closed (focus is back on the trigger), to open the create sheet. */\n onCreate: () => void;\n /** Where focus goes on close when the trigger is gone (the relation is full). */\n onFocusFallback: () => void;\n};\n\n/**\n * Finds and links entries of a relation's target model (DESIGN.md \"Dialogs\": pickers). From `md` up it is a\n * modal popover anchored to the field; below, the same body in a bottom sheet. In multi mode every pick\n * links at once and the picker stays open; \"Create new\" closes it before the create sheet opens.\n */\nexport const RelationPicker = ({\n open,\n onOpenChange,\n trigger,\n target,\n multiple,\n selected,\n exclude,\n locale,\n full,\n canCreate,\n onPick,\n onUnpick,\n onCreate,\n onFocusFallback,\n}: RelationPickerProps) => {\n const { t } = useTranslation();\n const isMdUp = useIsMdUp();\n const titleId = useId();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const creatingRef = useRef(false);\n const title = t('content.relation.chooseTitle', { model: target.label });\n\n const pick = (id: string) => {\n onPick(id);\n if (!multiple) {\n onOpenChange(false);\n }\n };\n const startCreate = () => {\n creatingRef.current = true;\n onOpenChange(false);\n };\n /** Runs when the picker has closed: return focus ourselves when handing off or when the trigger is gone. */\n const onCloseAutoFocus = (event: Event) => {\n const creating = creatingRef.current;\n creatingRef.current = false;\n const trigger = triggerRef.current;\n if (!creating && trigger?.isConnected) {\n return;\n }\n event.preventDefault();\n if (trigger?.isConnected) {\n trigger.focus({ preventScroll: true });\n } else {\n onFocusFallback();\n }\n if (creating) {\n onCreate();\n }\n };\n\n const results = (listClassName?: string) => (\n <Results\n target={target}\n locale={locale}\n multiple={multiple}\n selected={selected}\n exclude={exclude}\n full={full}\n onPick={pick}\n onUnpick={onUnpick}\n className=\"flex-1\"\n listClassName={listClassName}\n />\n );\n const actions =\n canCreate || multiple ? (\n <>\n {canCreate ? (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" className=\"mr-auto\" onClick={startCreate}>\n <Plus aria-hidden=\"true\" />\n {t('content.relation.createNew', { model: target.label })}\n </Button>\n ) : null}\n {multiple ? (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => onOpenChange(false)}>\n {t('content.relation.done')}\n </Button>\n ) : null}\n </>\n ) : null;\n\n if (isMdUp) {\n return (\n <Popover open={open} onOpenChange={onOpenChange} modal>\n {trigger ? (\n <PopoverTrigger asChild ref={triggerRef}>\n {trigger}\n </PopoverTrigger>\n ) : null}\n <PopoverContent\n aria-labelledby={titleId}\n align=\"start\"\n collisionPadding={16}\n className=\"flex max-h-(--radix-popover-content-available-height) w-96 flex-col gap-3 p-3\"\n onCloseAutoFocus={onCloseAutoFocus}\n >\n <p id={titleId} className=\"text-sm font-semibold\">\n {title}\n </p>\n {results('max-h-72')}\n {actions ? (\n <div className=\"flex items-center justify-end gap-2 border-t pt-3\">{actions}</div>\n ) : null}\n </PopoverContent>\n </Popover>\n );\n }\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n {trigger ? (\n <SheetTrigger asChild ref={triggerRef}>\n {trigger}\n </SheetTrigger>\n ) : null}\n <SheetContent side=\"bottom\" aria-describedby={undefined} onCloseAutoFocus={onCloseAutoFocus}>\n <SheetHeader>\n <SheetTitle>{title}</SheetTitle>\n </SheetHeader>\n <SheetBody className=\"flex flex-col\">{results()}</SheetBody>\n {actions ? <SheetFooter>{actions}</SheetFooter> : null}\n </SheetContent>\n </Sheet>\n );\n};\n","import { ArrowDown, ArrowUp, Layers, Plus, X } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { IconTile } from '@/components/IconTile';\nimport { Button } from '@/components/ui/button';\nimport { Skeleton } from '@/components/ui/skeleton';\nimport { useFieldsEnvironment } from '../form/context';\nimport { entryTitle, shortId } from '../helpers/titles';\nimport { moveItem, toList } from '../helpers/values';\nimport { useEntryLabels } from '../hooks/useEntryLabels';\nimport type { BuiltInEditorProps } from '../types';\nimport { InlineCreateSheet } from './InlineCreateSheet';\nimport { RelationPicker } from './RelationPicker';\n\n/**\n * `relationPicker`: links to entries of another model, one or many (ordered). Entries are found by their\n * title in a picker anchored to the field; with `allowInlineCreate`, a new one can be created in a sheet\n * without leaving the form.\n */\nexport const RelationField = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const environment = useFieldsEnvironment();\n const { value, onChange, onBlur, readOnly, disabled, definition, field, inputId, labelId, describedBy } =\n props;\n const [searching, setSearching] = useState(false);\n const [creating, setCreating] = useState(false);\n const listRef = useRef<HTMLUListElement>(null);\n const settings = definition.type === 'relation' ? definition.settings : undefined;\n const target = settings ? environment.models.get(settings.target) : undefined;\n const multiple = settings?.cardinality === 'many';\n const ids = toList<string>(value).filter((id): id is string => typeof id === 'string');\n const labels = useEntryLabels(target, ids, environment.locale);\n if (!settings || !target) {\n return <p className=\"text-sm text-destructive\">{t('content.relation.targetMissing')}</p>;\n }\n const editable = !readOnly && !disabled;\n const commit = (next: string[]) => {\n onChange(multiple ? (next.length > 0 ? next : null) : (next[0] ?? null));\n onBlur();\n };\n const add = (id: string) => commit(multiple ? (ids.includes(id) ? ids : [...ids, id]) : [id]);\n const canAddMore = !multiple || settings.max === undefined || ids.length < settings.max;\n const labelFor = (id: string) => {\n const item = labels.byId.get(id);\n return item ? (entryTitle(target, item.data) ?? `${t('content.untitled')} · ${shortId(id)}`) : undefined;\n };\n return (\n <div role=\"group\" aria-labelledby={labelId} aria-describedby={describedBy} className=\"space-y-2\">\n {ids.length > 0 ? (\n <ul ref={listRef} className=\"space-y-2\">\n {ids.map((id, index) => {\n const label = labelFor(id);\n return (\n <li key={id} className=\"flex items-center gap-3 rounded-lg border bg-card p-2 pl-3\">\n <IconTile icon={Layers} />\n <span className=\"min-w-0 flex-1\">\n {label !== undefined ? (\n <span className=\"block truncate text-sm font-semibold\">{label}</span>\n ) : labels.isLoading ? (\n <Skeleton className=\"h-4 w-40\" />\n ) : (\n <span className=\"block truncate text-sm text-destructive\">\n {t('content.relation.missingEntry', { id: shortId(id) })}\n </span>\n )}\n <span className=\"block text-meta text-muted-foreground\">{target.label}</span>\n </span>\n {editable && multiple ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.moveUp', { item: label ?? id, position: index + 1 })}\n disabled={index === 0}\n onClick={() => commit(moveItem(ids, index, index - 1))}\n >\n <ArrowUp aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.items.moveDown', { item: label ?? id, position: index + 1 })}\n disabled={index === ids.length - 1}\n onClick={() => commit(moveItem(ids, index, index + 1))}\n >\n <ArrowDown aria-hidden=\"true\" />\n </Button>\n </>\n ) : null}\n {editable ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('content.relation.remove', { item: label ?? id })}\n onClick={() => commit(ids.filter((item) => item !== id))}\n >\n <X aria-hidden=\"true\" />\n </Button>\n ) : null}\n </li>\n );\n })}\n </ul>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('content.relation.empty')}</p>\n )}\n {editable ? (\n <RelationPicker\n open={searching}\n onOpenChange={setSearching}\n // Stays while the picker is open, so it remains anchored when the last allowed pick fills it.\n trigger={\n canAddMore || searching ? (\n <Button id={inputId} type=\"button\" variant=\"outline\" size=\"sm\">\n <Plus aria-hidden=\"true\" />\n {multiple\n ? t('content.relation.add', { model: target.label })\n : ids.length > 0\n ? t('content.relation.change')\n : t('content.relation.choose', { model: target.label })}\n </Button>\n ) : null\n }\n target={target}\n multiple={multiple}\n selected={ids}\n exclude={environment.entryId && target.id === environment.model.id ? [environment.entryId] : []}\n locale={environment.locale}\n full={!canAddMore}\n // TODO(per-model permissions in `me`): also require `create` on the target model. Until `me` carries\n // per-model permissions, a refusal shows as the server's 403 in the sheet.\n canCreate={field.options.allowInlineCreate === true}\n onPick={add}\n onUnpick={(id) => commit(ids.filter((item) => item !== id))}\n onCreate={() => setCreating(true)}\n // The relation is full and its button gone: focus the last linked entry's Unlink button.\n onFocusFallback={() =>\n listRef.current?.querySelector<HTMLElement>('li:last-child button:last-child')?.focus()\n }\n />\n ) : null}\n {creating ? (\n <InlineCreateSheet\n target={target}\n onClose={() => setCreating(false)}\n onCreated={(id) => {\n setCreating(false);\n add(id);\n }}\n />\n ) : null}\n </div>\n );\n};\n","'use client';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Toggle as TogglePrimitive } from 'radix-ui';\nimport * as React from 'react';\nimport { cn } from '@/helpers/cn';\n\nconst toggleVariants = cva(\n \"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: 'bg-transparent',\n outline: 'border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground',\n },\n size: {\n default: 'h-9 min-w-9 px-2',\n sm: 'h-8 min-w-8 px-1.5',\n lg: 'h-10 min-w-10 px-2.5',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nfunction Toggle({\n className,\n variant,\n size,\n ...props\n}: React.ComponentProps<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>) {\n return (\n <TogglePrimitive.Root\n data-slot=\"toggle\"\n className={cn(toggleVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Toggle, toggleVariants };\n","'use client';\n\nimport { type VariantProps } from 'class-variance-authority';\nimport { ToggleGroup as ToggleGroupPrimitive } from 'radix-ui';\nimport * as React from 'react';\nimport { toggleVariants } from '@/components/ui/toggle';\nimport { cn } from '@/helpers/cn';\n\nconst ToggleGroupContext = React.createContext<VariantProps<typeof toggleVariants>>({\n size: 'default',\n variant: 'default',\n});\n\nfunction ToggleGroup({\n className,\n variant,\n size,\n children,\n ...props\n}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & VariantProps<typeof toggleVariants>) {\n return (\n <ToggleGroupPrimitive.Root\n data-slot=\"toggle-group\"\n data-variant={variant}\n data-size={size}\n className={cn(\n 'group/toggle-group flex w-fit items-center rounded-md data-[variant=outline]:shadow-xs',\n className,\n )}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ variant, size }}>{children}</ToggleGroupContext.Provider>\n </ToggleGroupPrimitive.Root>\n );\n}\n\nfunction ToggleGroupItem({\n className,\n children,\n variant,\n size,\n ...props\n}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants>) {\n const context = React.useContext(ToggleGroupContext);\n\n return (\n <ToggleGroupPrimitive.Item\n data-slot=\"toggle-group-item\"\n data-variant={context.variant || variant}\n data-size={context.size || size}\n className={cn(\n toggleVariants({\n variant: context.variant || variant,\n size: context.size || size,\n }),\n 'min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l',\n className,\n )}\n {...props}\n >\n {children}\n </ToggleGroupPrimitive.Item>\n );\n}\n\nexport { ToggleGroup, ToggleGroupItem };\n","import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';\nimport { choicesOf, fromChoice, toChoice } from '../helpers/choices';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `segmented`: a row of buttons for a boolean or a single-choice enum. Pressing the active one clears it. */\nexport const Segmented = (props: BuiltInEditorProps) => {\n const { labelId, describedBy, value, onChange, onBlur, readOnly, disabled, validation } = props;\n return (\n <ToggleGroup\n type=\"single\"\n variant=\"outline\"\n aria-labelledby={labelId}\n aria-describedby={describedBy}\n aria-invalid={validation.invalid || undefined}\n value={toChoice(value)}\n disabled={disabled || readOnly}\n onValueChange={(choice) => onChange(fromChoice(props, choice))}\n onBlur={onBlur}\n className=\"flex-wrap\"\n >\n {choicesOf(props).map((choice) => (\n <ToggleGroupItem key={choice.value} value={choice.value} className=\"px-3\">\n {choice.label}\n </ToggleGroupItem>\n ))}\n </ToggleGroup>\n );\n};\n","import { ChevronDown } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { ClearButton } from '../ClearButton';\nimport { choicesOf, fromChoice, isMultiple, toChoice } from '../helpers/choices';\nimport { inputAria, stringOption } from '../helpers/props';\nimport { toList } from '../helpers/values';\nimport type { BuiltInEditorProps } from '../types';\n\nconst MultiSelect = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { value, onChange, readOnly, disabled, field } = props;\n const selected = toList<string>(value);\n const choices = choicesOf(props);\n const summary = choices\n .filter((choice) => selected.includes(choice.value))\n .map((choice) => choice.label)\n .join(', ');\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild disabled={disabled || readOnly}>\n <Button variant=\"outline\" {...inputAria(props)} className=\"w-full justify-between font-normal\">\n <span className=\"truncate\">\n {summary || stringOption(props, 'placeholder') || t('content.fields.choose')}\n </span>\n <ChevronDown aria-hidden=\"true\" className=\"opacity-50\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"start\"\n className=\"w-(--radix-dropdown-menu-trigger-width)\"\n aria-label={field.label}\n >\n {choices.map((choice) => (\n <DropdownMenuCheckboxItem\n key={choice.value}\n checked={selected.includes(choice.value)}\n onSelect={(event) => event.preventDefault()}\n onCheckedChange={(checked) =>\n onChange(\n checked\n ? choices\n .map((item) => item.value)\n .filter((item) => item === choice.value || selected.includes(item))\n : selected.filter((item) => item !== choice.value),\n )\n }\n >\n {choice.label}\n </DropdownMenuCheckboxItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n};\n\n/** `select`: a dropdown for an enum (a checkbox menu when the enum allows several values). */\nexport const SelectInput = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { value, onChange, onBlur, readOnly, disabled, field } = props;\n if (isMultiple(props)) {\n return <MultiSelect {...props} />;\n }\n const current = toChoice(value);\n return (\n <div className=\"flex items-center gap-1\">\n <Select\n value={current}\n disabled={disabled || readOnly}\n onValueChange={(choice) => onChange(fromChoice(props, choice))}\n >\n <SelectTrigger {...inputAria(props)} className=\"w-full\" onBlur={onBlur}>\n <SelectValue placeholder={stringOption(props, 'placeholder') ?? t('content.fields.choose')} />\n </SelectTrigger>\n <SelectContent>\n {choicesOf(props).map((choice) => (\n <SelectItem key={choice.value} value={choice.value}>\n {choice.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {current && !field.required && !readOnly ? (\n <ClearButton label={field.label} disabled={disabled} onClear={() => onChange(null)} />\n ) : null}\n </div>\n );\n};\n","import { useTranslation } from 'react-i18next';\nimport { cn } from '@/helpers/cn';\nimport type { SeoCounter } from '../helpers';\n\ntype CounterProps = { counter: SeoCounter };\n\n/** Characters used against the soft maximum, shown near and over it. Never an error: nothing is enforced. */\nexport const Counter = ({ counter }: CounterProps) => {\n const { t } = useTranslation();\n return (\n <p className={cn('text-meta tabular-nums', counter.over ? 'text-warning' : 'text-muted-foreground')}>\n {t(counter.over ? 'seo.field.counterOver' : 'seo.field.counter', {\n count: counter.count,\n max: counter.max,\n })}\n </p>\n );\n};\n","import type { Locale } from '@shapio/client';\nimport {\n resolveSeo,\n seoComponentDefinition,\n seoDefaultsForLocale,\n SEO_DESCRIPTION_SOFT_MAX,\n SEO_FIELD_IDS,\n SEO_TITLE_SOFT_MAX,\n type ComponentDefinition,\n type SeoDefaults,\n type SeoFieldKey,\n type SeoKeys,\n} from '@shapio/schema';\n\n/** A counter shows once the text is this close to its soft maximum (and stays while it is over). */\nexport const SEO_COUNTER_WINDOW = 10;\n\nconst SOFT_MAX_BY_FIELD_ID: Readonly<Record<string, number>> = {\n [SEO_FIELD_IDS.title]: SEO_TITLE_SOFT_MAX,\n [SEO_FIELD_IDS.description]: SEO_DESCRIPTION_SOFT_MAX,\n};\n\nexport type SeoCounter = { count: number; max: number; over: boolean };\n\n/**\n * The length counter under the SEO title or description (by stable field ID), or null when hidden: the field\n * has no soft maximum, or its text is more than `SEO_COUNTER_WINDOW` characters short of it.\n */\nexport const seoCounterOf = (fieldId: string, value: unknown): SeoCounter | null => {\n const max = SOFT_MAX_BY_FIELD_ID[fieldId];\n if (max === undefined) {\n return null;\n }\n const count = typeof value === 'string' ? [...value].length : 0;\n return count >= max - SEO_COUNTER_WINDOW ? { count, max, over: count > max } : null;\n};\n\nconst BUILT_IN_TYPES = new Map(seoComponentDefinition().fields.map((field) => [field.id, field.type]));\n\n/**\n * Where each built-in SEO field sits in a value of `component` (its API IDs may have been renamed): looked\n * up by stable ID; a removed or retyped field is left out, like the server's resolver does.\n */\nexport const seoKeysOf = (component: ComponentDefinition): SeoKeys => {\n const keys: SeoKeys = {};\n for (const [key, id] of Object.entries(SEO_FIELD_IDS) as [SeoFieldKey, string][]) {\n const field = component.fields.find((candidate) => candidate.id === id && !candidate.deprecated);\n if (field && field.type === BUILT_IN_TYPES.get(id)) {\n keys[key] = field.apiKey;\n }\n }\n return keys;\n};\n\n/** The locale, its configured fallbacks, then the default locale: the order delivery reads them in. */\nexport const localeChainOf = (locales: readonly Locale[], code: string | null): string[] => {\n const fallbackLocale = locales.find((locale) => locale.isDefault)?.code;\n const start = code ?? fallbackLocale;\n const configured = locales.find((locale) => locale.code === start)?.fallbacks ?? [];\n const chain = [start, ...configured, fallbackLocale].filter(\n (entry): entry is string => entry !== undefined && locales.some((locale) => locale.code === entry),\n );\n return chain.filter((entry, index) => chain.indexOf(entry) === index);\n};\n\nexport type SeoPreview = {\n /** The title as search results show it (through the site's template), or null when there is none. */\n title: string | null;\n description: string | null;\n /** The site's name for the result's URL line, when the defaults set one. */\n siteName: string | null;\n};\n\ntype SeoPreviewInput = {\n value: unknown;\n component: ComponentDefinition;\n defaults: SeoDefaults;\n localeChain: readonly string[];\n /** The entry's own title, used when the SEO title is empty. */\n fallbackTitle: unknown;\n};\n\n/** What a search result would show for this SEO value: the same rules as delivery's `seo=resolved`. */\nexport const seoPreviewOf = ({\n value,\n component,\n defaults,\n localeChain,\n fallbackTitle,\n}: SeoPreviewInput): SeoPreview => {\n const keys = seoKeysOf(component);\n const localeDefaults = seoDefaultsForLocale(defaults, localeChain);\n const resolved = resolveSeo(value, {\n defaults: localeDefaults,\n image: null,\n fallbackTitle: typeof fallbackTitle === 'string' ? fallbackTitle : null,\n keys,\n });\n const text = (key: SeoFieldKey) => {\n const entry = keys[key] === undefined ? undefined : resolved[keys[key]];\n return typeof entry === 'string' && entry.trim() !== '' ? entry : null;\n };\n return {\n title: keys.title === undefined ? null : text('title'),\n description: text('description'),\n siteName: localeDefaults.siteName ?? null,\n };\n};\n","import { effectiveTitleField, type ComponentDefinition } from '@shapio/schema';\nimport { useMemo } from 'react';\nimport { useMe } from '@/api/auth';\nimport { useLocales } from '@/api/locales';\nimport { useSiteSeoDefaults } from '@/api/seo';\nimport { useEntryForm, useFieldsEnvironment } from '../../form/context';\nimport { localeChainOf, seoPreviewOf, type SeoPreview } from '../helpers';\n\nexport type SeoPreviewWithSlug = SeoPreview & {\n /** The URL line: the site's SEO name (else its admin name) and the entry's slug, when it has one. */\n urlLine: string;\n};\n\n/**\n * The search-result preview of an SEO value in the entry being edited: the entry's title and slug from the\n * form, the site's defaults for the locale being edited (through its fallback chain).\n */\nexport const useSeoPreview = (component: ComponentDefinition, value: unknown): SeoPreviewWithSlug => {\n const { model, locale } = useFieldsEnvironment();\n const defaults = useSiteSeoDefaults();\n const locales = useLocales().data;\n const siteName = useMe().data?.site.name ?? '';\n const titleKey = effectiveTitleField(model)?.apiKey;\n const slugKey = model.fields.find((field) => field.type === 'slug' && !field.deprecated)?.apiKey;\n const fallbackTitle = useEntryForm((state) => (titleKey ? state.values[titleKey] : undefined));\n const slug = useEntryForm((state) => (slugKey ? state.values[slugKey] : undefined));\n return useMemo(() => {\n const preview = seoPreviewOf({\n value,\n component,\n defaults,\n localeChain: localeChainOf(locales ?? [], locale),\n fallbackTitle,\n });\n const host = preview.siteName ?? siteName;\n const urlLine = typeof slug === 'string' && slug !== '' ? `${host} › ${slug}` : host;\n return { ...preview, urlLine };\n }, [value, component, defaults, locales, locale, fallbackTitle, siteName, slug]);\n};\n","import { useId } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { SeoPreviewWithSlug } from '../hooks/useSeoPreview';\n\ntype PreviewProps = { preview: SeoPreviewWithSlug; noindex: boolean };\n\n/** How a search result could show the entry: URL line, title (through the site's template), description. */\nexport const Preview = ({ preview, noindex }: PreviewProps) => {\n const { t } = useTranslation();\n const headingId = useId();\n return (\n <section aria-labelledby={headingId} className=\"space-y-2 rounded-lg border bg-muted/40 p-4\">\n <h4 id={headingId} className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n {t('seo.field.preview')}\n </h4>\n <div className=\"min-w-0 space-y-0.5\">\n <p className=\"truncate text-meta text-muted-foreground\">{preview.urlLine}</p>\n <p className=\"line-clamp-2 text-base font-semibold break-words text-link\">\n {preview.title ?? t('seo.field.noTitle')}\n </p>\n {preview.description ? (\n <p className=\"line-clamp-3 text-sm break-words text-muted-foreground\">{preview.description}</p>\n ) : null}\n </div>\n {noindex ? <p className=\"text-meta text-warning\">{t('seo.field.noindex')}</p> : null}\n </section>\n );\n};\n","import { isSeoField, type ComponentDefinition, type FieldDefinition } from '@shapio/schema';\nimport { useCallback, useMemo } from 'react';\nimport { ComponentField } from '../ComponentField';\nimport { ComponentItemFields } from '../ComponentItemFields';\nimport { useFieldsEnvironment } from '../form/context';\nimport { newComponentItem } from '../helpers/formValues';\nimport { isRecord, type ItemValues } from '../helpers/values';\nimport type { BuiltInEditorProps } from '../types';\nimport { Counter } from './Counter';\nimport { seoCounterOf, seoKeysOf } from './helpers';\nimport { useSeoPreview } from './hooks/useSeoPreview';\nimport { Preview } from './Preview';\n\ntype SeoGroupProps = BuiltInEditorProps & { component: ComponentDefinition };\n\nconst renderCounter = (field: FieldDefinition, value: unknown) => {\n const counter = seoCounterOf(field.id, value);\n return counter ? <Counter counter={counter} /> : null;\n};\n\n/** The SEO group: its fields shown at once (an empty value starts on the first edit), counters, preview. */\nconst SeoGroup = ({ component, value, onChange, path }: SeoGroupProps) => {\n const item = useMemo(\n () => (isRecord(value) ? value : newComponentItem(component, false)),\n [value, component],\n );\n const onItemChange = useCallback((next: ItemValues) => onChange(next), [onChange]);\n const preview = useSeoPreview(component, value);\n const noindexKey = seoKeysOf(component).noindex;\n return (\n <div className=\"space-y-4 rounded-xl border bg-card p-5\">\n <ComponentItemFields\n component={component}\n item={item}\n onItemChange={onItemChange}\n path={path}\n renderFieldFooter={renderCounter}\n />\n <Preview preview={preview} noindex={noindexKey !== undefined && item[noindexKey] === true} />\n </div>\n );\n};\n\n/**\n * `seoEditor`: the built-in SEO component's fields with length counters on title and description and a\n * search-result preview. Any other component field (the editor chosen by hand) gets the plain component\n * editor.\n */\nexport const SeoField = (props: BuiltInEditorProps) => {\n const { components } = useFieldsEnvironment();\n const { definition } = props;\n const component =\n definition.type === 'component' && isSeoField(definition)\n ? components.get(definition.settings.component)\n : undefined;\n return component ? <SeoGroup {...props} component={component} /> : <ComponentField {...props} />;\n};\n","/** Text → `lower-case-words-with-hyphens` (the `slug` format), dropping accents and punctuation. */\nexport const slugify = (text: string): string =>\n text\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n","import { Link2, Link2Off } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { useSiblingValues } from '../form/context';\nimport { inputAria, stringOption, textValue } from '../helpers/props';\nimport { slugify } from '../helpers/slugify';\nimport type { BuiltInEditorProps } from '../types';\n\n/** The text of the field a slug is generated from (`settings.sourceFieldId`, usually the title). */\nconst useSourceText = (props: BuiltInEditorProps): string | undefined => {\n const siblings = useSiblingValues();\n const sourceId = props.definition.type === 'slug' ? props.definition.settings.sourceFieldId : undefined;\n const source = siblings?.definition.fields.find((field) => field.id === sourceId);\n if (!source) {\n return undefined;\n }\n const value = siblings?.values[source.apiKey];\n return typeof value === 'string' ? value : '';\n};\n\n/**\n * `slugInput`: a URL slug that follows its source field (e.g. the title) until someone edits it by hand.\n * The lock button switches between following the source and keeping the slug as typed.\n */\nexport const SlugInput = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { value, onChange, onBlur, readOnly, disabled } = props;\n const sourceText = useSourceText(props);\n const text = textValue(value);\n const [following, setFollowing] = useState(\n () => sourceText !== undefined && (text === '' || text === slugify(sourceText)),\n );\n const lastSource = useRef(sourceText);\n useEffect(() => {\n if (sourceText === undefined || sourceText === lastSource.current) {\n return;\n }\n lastSource.current = sourceText;\n if (following && !readOnly) {\n const next = slugify(sourceText);\n onChange(next === '' ? null : next);\n }\n }, [sourceText, following, readOnly, onChange]);\n return (\n <div className=\"flex items-center gap-1\">\n <Input\n {...inputAria(props)}\n value={text}\n placeholder={stringOption(props, 'placeholder')}\n readOnly={readOnly}\n disabled={disabled}\n spellCheck={false}\n className=\"font-mono text-sm\"\n onChange={(event) => {\n setFollowing(false);\n onChange(event.target.value === '' ? null : event.target.value);\n }}\n onBlur={() => {\n // Tidy what was typed into the slug format when leaving the field.\n if (text && slugify(text) !== text) {\n onChange(slugify(text) || null);\n }\n onBlur();\n }}\n />\n {sourceText !== undefined && !readOnly ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-pressed={following}\n aria-label={following ? t('content.fields.slug.unlink') : t('content.fields.slug.link')}\n title={following ? t('content.fields.slug.unlink') : t('content.fields.slug.link')}\n disabled={disabled}\n onClick={() => {\n if (!following) {\n const next = slugify(sourceText);\n onChange(next === '' ? null : next);\n }\n setFollowing(!following);\n }}\n >\n {following ? <Link2 aria-hidden=\"true\" /> : <Link2Off aria-hidden=\"true\" />}\n </Button>\n ) : null}\n </div>\n );\n};\n","import { useTranslation } from 'react-i18next';\nimport { Textarea as TextareaControl } from '@/components/ui/textarea';\nimport { inputAria, numberOption, stringOption, textValue } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\nconst DEFAULT_ROWS = 4;\n\n/** `textarea`: several lines of plain text, with a character count when the field has a maximum. */\nexport const Textarea = (props: BuiltInEditorProps) => {\n const { t } = useTranslation();\n const { inputId, value, onChange, onBlur, readOnly, disabled, definition } = props;\n const text = textValue(value);\n const maxLength = 'maxLength' in definition.settings ? definition.settings.maxLength : undefined;\n const countId = `${inputId}-count`;\n return (\n <div className=\"space-y-1\">\n <TextareaControl\n {...inputAria(props, maxLength ? countId : undefined)}\n rows={numberOption(props, 'rows') ?? DEFAULT_ROWS}\n value={text}\n placeholder={stringOption(props, 'placeholder')}\n readOnly={readOnly}\n disabled={disabled}\n onChange={(event) => onChange(event.target.value === '' ? null : event.target.value)}\n onBlur={onBlur}\n />\n {maxLength ? (\n <p id={countId} className=\"text-right text-meta text-muted-foreground tabular-nums\">\n {t('content.fields.characterCount', { count: text.length, max: maxLength })}\n </p>\n ) : null}\n </div>\n );\n};\n","import { Input } from '@/components/ui/input';\nimport { inputAria, stringOption, textValue } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\nconst INPUT_TYPES: Partial<Record<string, 'email' | 'url'>> = { email: 'email', url: 'url' };\n\n/** `textInput`: one line of text (string, email, URL, UID). */\nexport const TextInput = (props: BuiltInEditorProps) => {\n const { value, onChange, onBlur, readOnly, disabled, definition } = props;\n const maxLength = 'maxLength' in definition.settings ? definition.settings.maxLength : undefined;\n return (\n <Input\n {...inputAria(props)}\n type={INPUT_TYPES[definition.type] ?? 'text'}\n value={textValue(value)}\n placeholder={stringOption(props, 'placeholder')}\n maxLength={maxLength}\n readOnly={readOnly}\n disabled={disabled}\n spellCheck={definition.type === 'string'}\n onChange={(event) => onChange(event.target.value === '' ? null : event.target.value)}\n onBlur={onBlur}\n />\n );\n};\n","import { Input } from '@/components/ui/input';\nimport { ClearButton } from '../ClearButton';\nimport { inputAria, numberOption, textValue } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\nconst SECONDS_PER_MINUTE = 60;\n\n/** `timePicker`: a time of day stored as `HH:mm` (or `HH:mm:ss`), with an optional minute step. */\nexport const TimeInput = (props: BuiltInEditorProps) => {\n const { value, onChange, onBlur, readOnly, disabled, field } = props;\n const text = textValue(value);\n return (\n <div className=\"flex items-center gap-1\">\n <Input\n {...inputAria(props)}\n type=\"time\"\n value={text}\n step={(numberOption(props, 'stepMinutes') ?? 1) * SECONDS_PER_MINUTE}\n readOnly={readOnly}\n disabled={disabled}\n className=\"w-auto\"\n onChange={(event) => onChange(event.target.value === '' ? null : event.target.value)}\n onBlur={onBlur}\n />\n {text && !readOnly ? (\n <ClearButton label={field.label} disabled={disabled} onClear={() => onChange(null)} />\n ) : null}\n </div>\n );\n};\n","import { Switch } from '@/components/ui/switch';\nimport { inputAria } from '../helpers/props';\nimport type { BuiltInEditorProps } from '../types';\n\n/** `toggle`: an on/off switch for booleans. */\nexport const Toggle = (props: BuiltInEditorProps) => {\n const { value, onChange, onBlur, readOnly, disabled } = props;\n return (\n <Switch\n {...inputAria(props)}\n checked={value === true}\n disabled={disabled || readOnly}\n onCheckedChange={(checked) => onChange(checked)}\n onBlur={onBlur}\n />\n );\n};\n","import type { EditorDefinition } from '@shapio/editor-sdk';\nimport {\n DEFAULT_EDITORS,\n EDITOR_CATALOGUE,\n isCustomEditorId,\n SEO_EDITOR_ID,\n type FieldDefinition,\n} from '@shapio/schema';\nimport { lazy } from 'react';\nimport { CheckboxGroup } from './CheckboxGroup';\nimport { CheckboxInput } from './CheckboxInput';\nimport { ColorInput } from './ColorInput';\nimport { ComponentField } from './ComponentField';\nimport { DateInput } from './DateInput';\nimport { DateTimeInput } from './DateTimeInput';\nimport { DynamicZoneField } from './DynamicZoneField';\nimport { JsonEditor } from './JsonEditor';\nimport { MediaField } from './MediaField';\nimport { NumberInput } from './NumberInput';\nimport { RadioInput } from './RadioInput';\nimport { RelationField } from './RelationField';\nimport { Segmented } from './Segmented';\nimport { SelectInput } from './SelectInput';\nimport { SeoField } from './SeoField';\nimport { SlugInput } from './SlugInput';\nimport { Textarea } from './Textarea';\nimport { TextInput } from './TextInput';\nimport { TimeInput } from './TimeInput';\nimport { Toggle } from './Toggle';\nimport type { BuiltInEditor } from './types';\n\n/** Tiptap and ProseMirror are most of the editor code: loaded only when a form has a rich-text field. */\nconst RichTextField = lazy(() =>\n import('./RichTextField').then((module) => ({ default: module.RichTextField })),\n);\n\n/** CodeMirror and its language packs: loaded only when a form has a code field. */\nconst CodeEditor = lazy(() => import('./CodeEditor').then((module) => ({ default: module.CodeEditor })));\n\n/** Built-in editors by catalogue ID (`EDITOR_CATALOGUE` in @shapio/schema). */\nexport const BUILT_IN_EDITORS: Readonly<Record<string, BuiltInEditor>> = {\n textInput: { component: TextInput, labelling: 'input' },\n textarea: { component: Textarea, labelling: 'input' },\n color: { component: ColorInput, labelling: 'input' },\n richText: { component: RichTextField, labelling: 'group' },\n numberInput: { component: NumberInput, labelling: 'input' },\n toggle: { component: Toggle, labelling: 'input' },\n checkbox: { component: CheckboxInput, labelling: 'input' },\n segmented: { component: Segmented, labelling: 'group' },\n select: { component: SelectInput, labelling: 'input' },\n radio: { component: RadioInput, labelling: 'group' },\n checkboxGroup: { component: CheckboxGroup, labelling: 'group' },\n datePicker: { component: DateInput, labelling: 'input' },\n dateTimePicker: { component: DateTimeInput, labelling: 'input' },\n timePicker: { component: TimeInput, labelling: 'input' },\n slugInput: { component: SlugInput, labelling: 'input' },\n jsonEditor: { component: JsonEditor, labelling: 'input' },\n codeEditor: { component: CodeEditor, labelling: 'group' },\n mediaPicker: { component: MediaField, labelling: 'group' },\n relationPicker: { component: RelationField, labelling: 'group' },\n componentEditor: { component: ComponentField, labelling: 'group' },\n dynamicZoneEditor: { component: DynamicZoneField, labelling: 'group' },\n [SEO_EDITOR_ID]: { component: SeoField, labelling: 'group' },\n};\n\n/** The built-in editor for a field: its chosen one when compatible, otherwise its data type's default. */\nexport const builtInEditorFor = (field: FieldDefinition): BuiltInEditor => {\n const chosen = BUILT_IN_EDITORS[field.editor.id];\n const compatible = EDITOR_CATALOGUE.get(field.editor.id)?.dataTypes.includes(field.type) ?? false;\n const fallback = BUILT_IN_EDITORS[DEFAULT_EDITORS[field.type]];\n if (!fallback) {\n throw new Error(`No built-in editor for data type ${field.type}`);\n }\n return chosen && compatible ? chosen : fallback;\n};\n\nexport type ResolvedEditor =\n | { kind: 'builtIn'; editor: BuiltInEditor; missingCustomId: string | undefined }\n | { kind: 'runtime'; definition: EditorDefinition; fallback: BuiltInEditor };\n\n/** Which editor renders a field: a project's custom editor when installed and compatible, else a built-in. */\nexport const resolveEditor = (\n field: FieldDefinition,\n runtimeEditors: ReadonlyMap<string, EditorDefinition>,\n): ResolvedEditor => {\n const builtIn = builtInEditorFor(field);\n if (!isCustomEditorId(field.editor.id)) {\n return { kind: 'builtIn', editor: builtIn, missingCustomId: undefined };\n }\n const custom = runtimeEditors.get(field.editor.id);\n if (custom && (custom.dataTypes as readonly string[]).includes(field.type)) {\n return { kind: 'runtime', definition: custom, fallback: builtIn };\n }\n return { kind: 'builtIn', editor: builtIn, missingCustomId: field.editor.id };\n};\n","import type { FieldEditorProps } from '@shapio/editor-sdk';\nimport type { FieldDefinition, SchemaDefinition } from '@shapio/schema';\nimport { useCallback, useMemo } from 'react';\nimport { useEntryForm, useFieldsEnvironment } from '../form/context';\nimport { clientIssuesOf } from '../helpers/clientValidation';\nimport { fieldDomId } from '../helpers/domIds';\nimport { toEditorContext, toEditorField, toEditorModel } from '../helpers/editorContext';\nimport { describeIssue } from '../helpers/issues';\nimport { resolveEditor } from '../registry';\nimport type { BuiltInEditorProps, EditorAppearance } from '../types';\n\nexport type FieldControlOptions = {\n field: FieldDefinition;\n /** The model or component the field belongs to. */\n owner: SchemaDefinition;\n value: unknown;\n onChange: (value: unknown) => void;\n /** JSON pointer of the value, e.g. `/hero/title` (issues use the same paths). */\n path: string;\n appearance?: EditorAppearance;\n};\n\n/** Component and dynamic-zone editors render nested fields, which show their own issues. */\nconst NESTING_TYPES: ReadonlySet<string> = new Set(['component', 'dynamiczone']);\n\nconst useFieldMessages = (field: FieldDefinition, value: unknown, path: string): string[] => {\n const serverIssues = useEntryForm((state) => state.issues);\n const revealed = useEntryForm((state) => state.revealAll || state.touched.has(path));\n return useMemo(() => {\n const nesting = NESTING_TYPES.has(field.type);\n const server = serverIssues.filter(\n (issue) =>\n issue.path === path ||\n (issue.path.startsWith(`${path}/`) && (!nesting || issue.path === `${path}/__component`)),\n );\n const client = revealed\n ? clientIssuesOf(field, value).filter((issue) => !server.some((known) => known.code === issue.code))\n : [];\n return [...new Set([...server, ...client].map((issue) => describeIssue(issue, field)))];\n }, [field, value, path, serverIssues, revealed]);\n};\n\n/**\n * Everything a field's chrome needs, whatever it looks like (a labelled form row, a canvas block, a\n * property chip): which editor renders it (a project's custom editor or a built-in), the props for it, the\n * DOM ids that tie label, description and errors together, and the messages to show (server issues for this\n * path, plus client-side checks once the field was left or a save was attempted).\n */\nexport const useFieldControl = ({\n field,\n owner,\n value,\n onChange,\n path,\n appearance = 'form',\n}: FieldControlOptions) => {\n const environment = useFieldsEnvironment();\n const touch = useEntryForm((state) => state.touch);\n const messages = useFieldMessages(field, value, path);\n const onBlur = useCallback(() => touch(path), [touch, path]);\n const resolved = useMemo(\n () => resolveEditor(field, environment.runtimeEditors),\n [field, environment.runtimeEditors],\n );\n const inputId = fieldDomId(environment.idPrefix, path);\n const labelId = `${inputId}-label`;\n const descriptionId = field.description ? `${inputId}-description` : undefined;\n const errorsId = messages.length > 0 ? `${inputId}-errors` : undefined;\n const describedBy = [descriptionId, errorsId].filter(Boolean).join(' ') || undefined;\n const editorField = useMemo(() => toEditorField(field), [field]);\n const editorModel = useMemo(() => toEditorModel(owner), [owner]);\n const context = useMemo(() => toEditorContext(environment), [environment]);\n const builtInProps: BuiltInEditorProps = {\n inputId,\n labelId,\n describedBy,\n value: value ?? null,\n onChange,\n onBlur,\n validation: { errors: messages, invalid: messages.length > 0 },\n readOnly: environment.readOnly,\n disabled: environment.disabled,\n field: editorField,\n model: editorModel,\n context,\n definition: field,\n path,\n appearance,\n };\n // Custom editors get exactly the public contract: no definition internals, no form paths, no appearance.\n const { definition: _definition, path: _path, appearance: _appearance, ...contractProps } = builtInProps;\n const builtIn = resolved.kind === 'builtIn' ? resolved.editor : resolved.fallback;\n return {\n resolved,\n builtIn,\n builtInProps,\n contractProps: contractProps as FieldEditorProps,\n /** How the label points at the editor: `<label for>` (one input) or `aria-labelledby` (a group). */\n labelling: resolved.kind === 'runtime' ? ('input' as const) : builtIn.labelling,\n inputId,\n labelId,\n descriptionId,\n errorsId,\n messages,\n };\n};\n\nexport type FieldControlState = ReturnType<typeof useFieldControl>;\n","import { useQuery } from '@tanstack/react-query';\nimport { adminApi } from './client';\nimport { queryKeys } from './queryKeys';\n\n/** Custom field editors the project installed. Changes only with a server restart, so read once. */\nexport const useEditorManifest = () =>\n useQuery({\n queryKey: queryKeys.editorManifest,\n queryFn: () => adminApi.extensions.editors(),\n staleTime: Infinity,\n meta: { silent: true },\n });\n","import type { EditorManifest } from '@shapio/client';\nimport { EDITOR_CONTRACT_VERSION, isEditorDefinition, type EditorDefinition } from '@shapio/editor-sdk';\nimport { apiBaseUrl } from '@/api/client';\nimport { logError } from '@/helpers/reportError';\n\n/**\n * Loads the project's custom field editors (ADR 0009). Each manifest entry is an ES module served by the\n * API; it imports `react` and `@shapio/editor-sdk` as bare specifiers, which the admin's import map resolves\n * to the admin's own instances. Any export that is an editor definition registers that editor.\n */\nexport type EditorLoadProblem = {\n file: string;\n reason: 'importFailed' | 'noEditor' | 'contractVersion' | 'duplicateId';\n detail?: string;\n};\n\nexport type RuntimeEditors = {\n editors: ReadonlyMap<string, EditorDefinition>;\n problems: readonly EditorLoadProblem[];\n};\n\nexport const NO_RUNTIME_EDITORS: RuntimeEditors = { editors: new Map(), problems: [] };\n\n/** The module's URL: manifest paths are relative to the server's base URL (`{BASE_PATH}/`). */\nexport const editorModuleUrl = (path: string, base: string = apiBaseUrl()) =>\n new URL(path.replace(/^\\/+/, ''), base).href;\n\ntype ImportModule = (url: string) => Promise<Record<string, unknown>>;\n\nconst importModule: ImportModule = (url) =>\n import(/* @vite-ignore */ url) as Promise<Record<string, unknown>>;\n\nexport const loadRuntimeEditors = async (\n manifest: EditorManifest,\n load: ImportModule = importModule,\n): Promise<RuntimeEditors> => {\n const editors = new Map<string, EditorDefinition>();\n const problems: EditorLoadProblem[] = [];\n for (const item of manifest.items) {\n let module: Record<string, unknown>;\n try {\n module = await load(editorModuleUrl(item.path));\n } catch (error) {\n logError(error, `loading custom editor ${item.file}`);\n problems.push({ file: item.file, reason: 'importFailed', detail: String(error) });\n continue;\n }\n const definitions = Object.values(module).filter(isEditorDefinition);\n if (definitions.length === 0) {\n problems.push({ file: item.file, reason: 'noEditor' });\n }\n for (const definition of definitions) {\n if (definition.contractVersion !== EDITOR_CONTRACT_VERSION) {\n problems.push({ file: item.file, reason: 'contractVersion', detail: definition.id });\n } else if (editors.has(definition.id)) {\n problems.push({ file: item.file, reason: 'duplicateId', detail: definition.id });\n } else {\n editors.set(definition.id, definition);\n }\n }\n }\n return { editors, problems };\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { useEditorManifest } from '@/api/editors';\nimport { loadRuntimeEditors, NO_RUNTIME_EDITORS, type RuntimeEditors } from './loader';\n\n/** The project's custom editors, imported once per session (they change only with a server restart). */\nexport const useRuntimeEditors = (): RuntimeEditors & { isLoading: boolean } => {\n const manifest = useEditorManifest();\n const modules = useQuery({\n queryKey: ['extensions', 'editors', 'modules', manifest.data ?? null],\n queryFn: () => loadRuntimeEditors(manifest.data ?? { items: [] }),\n enabled: manifest.data !== undefined,\n staleTime: Infinity,\n gcTime: Infinity,\n meta: { silent: true },\n });\n return {\n ...(modules.data ?? NO_RUNTIME_EDITORS),\n isLoading: manifest.isPending || (manifest.data !== undefined && modules.isPending),\n };\n};\n","import {\n collectionQueryName,\n isModelDefinition,\n MUTATION_PREFIXES,\n routeKeyOf,\n toTypeName,\n type FieldDefinition,\n type SchemaDefinition,\n} from '@shapio/schema';\n\n/**\n * The API shapes a definition produces, derived from the registry naming helpers in `@shapio/schema`\n * (`routeKeyOf`, `toTypeName`, `collectionQueryName`, `MUTATION_PREFIXES`), the same names the server's\n * OpenAPI and GraphQL builders use. Previews of a definition being edited, before it exists on the server.\n */\nexport type DefinitionLookup = ReadonlyMap<string, SchemaDefinition>;\n\nexport type RestEndpoint = {\n method: 'GET' | 'POST' | 'PUT' | 'DELETE';\n path: string;\n scope: 'delivery' | 'admin';\n};\n\nconst liveFields = (definition: SchemaDefinition) => definition.fields.filter((field) => !field.deprecated);\n\nexport const restEndpoints = (definition: SchemaDefinition): RestEndpoint[] => {\n if (!isModelDefinition(definition)) {\n return [];\n }\n const delivery = `/api/content/${routeKeyOf(definition)}`;\n const admin = `/api/admin/content/${definition.apiKey}`;\n const collection = definition.kind === 'collection';\n return [\n { method: 'GET', path: delivery, scope: 'delivery' },\n ...(collection ? [{ method: 'GET' as const, path: `${delivery}/{id}`, scope: 'delivery' as const }] : []),\n { method: 'GET', path: admin, scope: 'admin' },\n { method: 'POST', path: admin, scope: 'admin' },\n { method: 'GET', path: `${admin}/{id}`, scope: 'admin' },\n { method: 'PUT', path: `${admin}/{id}`, scope: 'admin' },\n { method: 'DELETE', path: `${admin}/{id}`, scope: 'admin' },\n { method: 'POST', path: `${admin}/{id}/publish`, scope: 'admin' },\n { method: 'POST', path: `${admin}/{id}/unpublish`, scope: 'admin' },\n ];\n};\n\n/** Delivery's default rich-text shape (`richText=json`); `html` and `both` add the rendered HTML. */\nconst RICH_TEXT_SAMPLE = {\n format: 'shapio-richtext',\n version: 1,\n doc: { type: 'doc', content: [] },\n};\n\nconst MEDIA_SAMPLE = { id: '<uuid>', url: '<url>', mimeType: '<mime type>', alt: '' };\n\n/** Nesting depth for component samples (components inside components show as `{}` below it). */\nconst MAX_SAMPLE_DEPTH = 2;\n\nconst sampleValue = (field: FieldDefinition, lookup: DefinitionLookup, depth: number): unknown => {\n const many = (multiple: boolean, value: unknown) => (multiple ? [value] : value);\n switch (field.type) {\n case 'number':\n case 'integer':\n return 0;\n case 'boolean':\n return false;\n case 'json':\n return {};\n case 'richtext':\n return RICH_TEXT_SAMPLE;\n case 'media':\n return many(field.settings.multiple, MEDIA_SAMPLE);\n case 'enum':\n return many(field.settings.multiple, field.settings.values[0]?.value ?? '');\n case 'relation':\n return many(field.settings.cardinality === 'many', '<entry id>');\n case 'component': {\n const component = lookup.get(field.settings.component);\n return many(field.settings.repeatable, component ? sampleObject(component, lookup, depth + 1) : {});\n }\n case 'dynamiczone':\n return field.settings.components.slice(0, 1).flatMap((id) => {\n const component = lookup.get(id);\n return component\n ? [{ __component: component.apiKey, ...sampleObject(component, lookup, depth + 1) }]\n : [];\n });\n default:\n return `<${field.type}>`;\n }\n};\n\nconst sampleObject = (\n definition: SchemaDefinition,\n lookup: DefinitionLookup,\n depth: number,\n): Record<string, unknown> =>\n depth > MAX_SAMPLE_DEPTH\n ? {}\n : Object.fromEntries(\n liveFields(definition).map((field) => [field.apiKey, sampleValue(field, lookup, depth)]),\n );\n\nconst SYSTEM_SAMPLE = {\n id: '<uuid>',\n locale: '<locale>',\n createdAt: '<datetime>',\n updatedAt: '<datetime>',\n publishedAt: '<datetime>',\n};\n\n/** An example delivery response (`GET /api/content/:routeKey`), as pretty JSON. */\nexport const restResponseSample = (definition: SchemaDefinition, lookup: DefinitionLookup): string => {\n const item = { ...SYSTEM_SAMPLE, ...sampleObject(definition, lookup, 0) };\n if (!isModelDefinition(definition)) {\n return JSON.stringify(sampleObject(definition, lookup, 0), null, 2);\n }\n const meta = { locale: '<locale>', snapshot: 0 };\n const body =\n definition.kind === 'collection'\n ? { data: [item], meta: { ...meta, pagination: { page: 1, pageSize: 25, pageCount: 1, total: 1 } } }\n : { data: item, meta };\n return JSON.stringify(body, null, 2);\n};\n\nconst listOf = (multiple: boolean, type: string) => (multiple ? `[${type}!]` : type);\n\nconst graphqlFieldType = (owner: SchemaDefinition, field: FieldDefinition, lookup: DefinitionLookup) => {\n const nameOf = (id: string) => {\n const target = lookup.get(id);\n return target ? toTypeName(target.apiKey) : 'JSON';\n };\n switch (field.type) {\n case 'number':\n return 'Float';\n case 'integer':\n return 'Int53';\n case 'boolean':\n return 'Boolean';\n case 'json':\n return 'JSON';\n case 'richtext':\n return 'RichText';\n case 'media':\n return listOf(field.settings.multiple, 'Media');\n case 'enum':\n return listOf(field.settings.multiple, `${toTypeName(owner.apiKey)}${toTypeName(field.apiKey)}Enum`);\n case 'relation':\n return listOf(field.settings.cardinality === 'many', nameOf(field.settings.target));\n case 'component':\n return listOf(field.settings.repeatable, nameOf(field.settings.component));\n case 'dynamiczone':\n return `[${toTypeName(owner.apiKey)}${toTypeName(field.apiKey)}Zone!]`;\n default:\n return 'String';\n }\n};\n\nconst READ_ARGS =\n 'locale: String, fallback: Boolean = true, publicationState: PublicationState = PUBLISHED, snapshot: Int';\n\n/** The definition's GraphQL type and (for models) its root queries and mutations, as SDL. */\nexport const graphqlSdl = (definition: SchemaDefinition, lookup: DefinitionLookup): string => {\n const name = toTypeName(definition.apiKey);\n const system = isModelDefinition(definition)\n ? [\n 'id: ID!',\n 'locale: String!',\n 'createdAt: String!',\n 'updatedAt: String!',\n 'publishedAt: String',\n `localizations: [${name}!]`,\n ]\n : [];\n const fields = liveFields(definition).map(\n (field) => `${field.apiKey}: ${graphqlFieldType(definition, field, lookup)}`,\n );\n const type = `type ${name} {\\n${[...system, ...fields].map((line) => ` ${line}`).join('\\n')}\\n}`;\n if (!isModelDefinition(definition)) {\n return `${type}\\n`;\n }\n const queries =\n definition.kind === 'collection'\n ? [\n `${definition.apiKey}(id: ID!, ${READ_ARGS}): ${name}`,\n `${collectionQueryName(definition)}(filter: ${name}Filter, sort: [${name}Sort!], search: String, page: Int, pageSize: Int, ${READ_ARGS}): ${name}Connection`,\n ]\n : [`${definition.apiKey}(${READ_ARGS}): ${name}`];\n const mutations = MUTATION_PREFIXES.map((prefix) => `${prefix}${name}`);\n return `${type}\\n\\ntype Query {\\n${queries.map((line) => ` ${line}`).join('\\n')}\\n}\\n\\n# Mutations: ${mutations.join(', ')}\\n`;\n};\n"],"file":"shapes-BJe3IMuj.js"}