@lattice-php/lattice 0.30.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action/components/action-form.js +26 -25
- package/dist/action/components/action-form.js.map +1 -1
- package/dist/action/components/action-group.js.map +1 -1
- package/dist/action/components/action-trigger-provider.js.map +1 -1
- package/dist/action/components/action.js.map +1 -1
- package/dist/action/lib/run-action.js +2 -1
- package/dist/action/lib/run-action.js.map +1 -1
- package/dist/appearance/index.js.map +1 -1
- package/dist/chat/components/chat-box.js +4 -2
- package/dist/chat/components/chat-box.js.map +1 -1
- package/dist/chat/components/message-list.js.map +1 -1
- package/dist/chat/components/message.js.map +1 -1
- package/dist/chat/components/prompt-input.js.map +1 -1
- package/dist/chat/hooks/use-chat.js +2 -1
- package/dist/chat/hooks/use-chat.js.map +1 -1
- package/dist/chat/lib/transport.js.map +1 -1
- package/dist/chat/parts/text.js.map +1 -1
- package/dist/chat/parts/tool-call.js.map +1 -1
- package/dist/core/api.js.map +1 -1
- package/dist/core/event-names.d.ts +1 -0
- package/dist/core/event-names.js +1 -0
- package/dist/core/event-names.js.map +1 -1
- package/dist/core/hooks/column-sizing.js.map +1 -1
- package/dist/core/hooks/use-column-resizing.js.map +1 -1
- package/dist/core/materialize.js.map +1 -1
- package/dist/core/registry-context.js.map +1 -1
- package/dist/core/renderer.js +2 -1
- package/dist/core/renderer.js.map +1 -1
- package/dist/core/test-id.js.map +1 -1
- package/dist/core/upload.js.map +1 -1
- package/dist/create-app.js +1 -1
- package/dist/create-app.js.map +1 -1
- package/dist/effects/registry.js +2 -1
- package/dist/effects/registry.js.map +1 -1
- package/dist/form/components/base/field.js.map +1 -1
- package/dist/form/components/base/submit-button.js.map +1 -1
- package/dist/form/components/fields/add-row-menu.js.map +1 -1
- package/dist/form/components/fields/builder.js +2 -1
- package/dist/form/components/fields/builder.js.map +1 -1
- package/dist/form/components/fields/checkbox.js.map +1 -1
- package/dist/form/components/fields/choice.js.map +1 -1
- package/dist/form/components/fields/color-picker-field.js.map +1 -1
- package/dist/form/components/fields/date-input.js.map +1 -1
- package/dist/form/components/fields/date-picker-field.js.map +1 -1
- package/dist/form/components/fields/date-picker-value.js.map +1 -1
- package/dist/form/components/fields/date-picker.js.map +1 -1
- package/dist/form/components/fields/date-time-input.js.map +1 -1
- package/dist/form/components/fields/file-upload.js +3 -2
- package/dist/form/components/fields/file-upload.js.map +1 -1
- package/dist/form/components/fields/number-input.js.map +1 -1
- package/dist/form/components/fields/otp-input.js.map +1 -1
- package/dist/form/components/fields/password-input.js.map +1 -1
- package/dist/form/components/fields/repeater.js +2 -1
- package/dist/form/components/fields/repeater.js.map +1 -1
- package/dist/form/components/fields/rich-editor-field.js +6 -5
- package/dist/form/components/fields/rich-editor-field.js.map +1 -1
- package/dist/form/components/fields/rich-editor.js.map +1 -1
- package/dist/form/components/fields/row-action-menu.js.map +1 -1
- package/dist/form/components/fields/row-actions.js.map +1 -1
- package/dist/form/components/fields/row-item.js.map +1 -1
- package/dist/form/components/fields/row-templates.js.map +1 -1
- package/dist/form/components/fields/select.js.map +1 -1
- package/dist/form/components/fields/simple-field.js.map +1 -1
- package/dist/form/components/fields/table-rows.js.map +1 -1
- package/dist/form/components/fields/text-input.js.map +1 -1
- package/dist/form/components/fields/textarea.js.map +1 -1
- package/dist/form/components/fields/time-input.js.map +1 -1
- package/dist/form/components/fields/time-picker-columns.js.map +1 -1
- package/dist/form/components/fields/time-picker.js +0 -1
- package/dist/form/components/fields/time-picker.js.map +1 -1
- package/dist/form/components/fields/toggle.js.map +1 -1
- package/dist/form/components/fields/use-flip-reorder.js.map +1 -1
- package/dist/form/components/form.js +7 -5
- package/dist/form/components/form.js.map +1 -1
- package/dist/form/components/wizard.js +1 -1
- package/dist/form/components/wizard.js.map +1 -1
- package/dist/form/hooks/resolved-nodes.js.map +1 -1
- package/dist/form/hooks/use-dependent-field.js +2 -1
- package/dist/form/hooks/use-dependent-field.js.map +1 -1
- package/dist/form/hooks/use-form-resolver.js +2 -1
- package/dist/form/hooks/use-form-resolver.js.map +1 -1
- package/dist/form/hooks/values.js +2 -1
- package/dist/form/hooks/values.js.map +1 -1
- package/dist/form/lib/conditions.js +1 -1
- package/dist/form/lib/conditions.js.map +1 -1
- package/dist/form/lib/field-dom-name.js.map +1 -1
- package/dist/form/lib/field-props.js +1 -1
- package/dist/form/lib/field-props.js.map +1 -1
- package/dist/form/lib/form-path.js.map +1 -1
- package/dist/form/lib/form-transport.js.map +1 -1
- package/dist/form/lib/prefill-targets.js.map +1 -1
- package/dist/form/lib/wizard-steps.js.map +1 -1
- package/dist/form/rich-editor/builtins.js.map +1 -1
- package/dist/format/date-time.d.ts +1 -0
- package/dist/format/date-time.js +5 -1
- package/dist/format/date-time.js.map +1 -1
- package/dist/format/number.js.map +1 -1
- package/dist/i18n/config.js.map +1 -1
- package/dist/i18n/date-time-formatter.d.ts +13 -0
- package/dist/i18n/date-time-formatter.js +28 -0
- package/dist/i18n/date-time-formatter.js.map +1 -0
- package/dist/i18n/date-time.js +1 -1
- package/dist/i18n/date-time.js.map +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/instance.js +2 -0
- package/dist/i18n/instance.js.map +1 -1
- package/dist/i18n/locale.js +1 -1
- package/dist/i18n/locale.js.map +1 -1
- package/dist/i18n/timezone.js.map +1 -1
- package/dist/i18n/translatable.js.map +1 -1
- package/dist/icons/icon-renderer.js.map +1 -1
- package/dist/icons/sprite.js.map +1 -1
- package/dist/layout/components/breadcrumbs.js.map +1 -1
- package/dist/layout/components/callouts.d.ts +2 -1
- package/dist/layout/components/callouts.js +6 -2
- package/dist/layout/components/callouts.js.map +1 -1
- package/dist/layout/components/dropdown.js.map +1 -1
- package/dist/layout/components/menu-item.js.map +1 -1
- package/dist/layout/components/menu.js.map +1 -1
- package/dist/layout/components/popover.js.map +1 -1
- package/dist/layout/components/schema-layout.js.map +1 -1
- package/dist/layout/components/sidebar.js.map +1 -1
- package/dist/lib/color.js +1 -1
- package/dist/lib/color.js.map +1 -1
- package/dist/lib/use-media-query.js.map +1 -1
- package/dist/notifications/components/empty-state.js.map +1 -1
- package/dist/notifications/components/notification-item.js.map +1 -1
- package/dist/notifications/components/notification-list.js.map +1 -1
- package/dist/notifications/components/notifications.js.map +1 -1
- package/dist/notifications/store.js.map +1 -1
- package/dist/page.js.map +1 -1
- package/dist/provider-base.js.map +1 -1
- package/dist/realtime/listeners.js.map +1 -1
- package/dist/remote/components/data-list.js.map +1 -1
- package/dist/table/components/bulk-bar.js.map +1 -1
- package/dist/table/components/cells/badge-cell.js.map +1 -1
- package/dist/table/components/cells/boolean-cell.js.map +1 -1
- package/dist/table/components/cells/icon-cell.js.map +1 -1
- package/dist/table/components/cells/numeric-cell.js.map +1 -1
- package/dist/table/components/cells/stack-cell.js.map +1 -1
- package/dist/table/components/cells/text-cell.js.map +1 -1
- package/dist/table/components/column-filter-control.js.map +1 -1
- package/dist/table/components/column-header.js.map +1 -1
- package/dist/table/components/column-visibility-menu.js +2 -1
- package/dist/table/components/column-visibility-menu.js.map +1 -1
- package/dist/table/components/filter-bar.js +2 -1
- package/dist/table/components/filter-bar.js.map +1 -1
- package/dist/table/components/filter-controls.js +6 -5
- package/dist/table/components/filter-controls.js.map +1 -1
- package/dist/table/components/filter-value-input.js.map +1 -1
- package/dist/table/components/pagination.d.ts +5 -1
- package/dist/table/components/pagination.js +25 -6
- package/dist/table/components/pagination.js.map +1 -1
- package/dist/table/components/sort-bar.js.map +1 -1
- package/dist/table/components/table-cell.js +2 -1
- package/dist/table/components/table-cell.js.map +1 -1
- package/dist/table/components/table-search.js.map +1 -1
- package/dist/table/components/table.js +6 -2
- package/dist/table/components/table.js.map +1 -1
- package/dist/table/hooks/use-column-visibility.js.map +1 -1
- package/dist/table/hooks/use-table-selection.js +2 -1
- package/dist/table/hooks/use-table-selection.js.map +1 -1
- package/dist/table/hooks/use-table.d.ts +2 -0
- package/dist/table/hooks/use-table.js +12 -0
- package/dist/table/hooks/use-table.js.map +1 -1
- package/dist/table/lib/bulk.js.map +1 -1
- package/dist/table/lib/filter-values.js.map +1 -1
- package/dist/table/lib/format.js.map +1 -1
- package/dist/table/lib/payload.d.ts +2 -0
- package/dist/table/lib/payload.js +18 -3
- package/dist/table/lib/payload.js.map +1 -1
- package/dist/table/lib/query.js +2 -1
- package/dist/table/lib/query.js.map +1 -1
- package/dist/toast/callout.d.ts +1 -0
- package/dist/toast/callout.js +9 -1
- package/dist/toast/callout.js.map +1 -1
- package/dist/toast/index.d.ts +1 -1
- package/dist/toast/index.js +2 -2
- package/dist/toast/toaster.js.map +1 -1
- package/dist/types/generated.d.ts +9 -1
- package/dist/ui/affix-group.js.map +1 -1
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/badge.js.map +1 -1
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/chart-view.js.map +1 -1
- package/dist/ui/chart.js.map +1 -1
- package/dist/ui/checkbox.js.map +1 -1
- package/dist/ui/collapsible.js.map +1 -1
- package/dist/ui/color-picker.js.map +1 -1
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/confirm-dialog.js.map +1 -1
- package/dist/ui/copyable-text.js.map +1 -1
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/floating-panel.js.map +1 -1
- package/dist/ui/fragment.js +2 -1
- package/dist/ui/fragment.js.map +1 -1
- package/dist/ui/heading.js.map +1 -1
- package/dist/ui/icon-button.js.map +1 -1
- package/dist/ui/icon.js.map +1 -1
- package/dist/ui/image-preview.js.map +1 -1
- package/dist/ui/info-tooltip.js.map +1 -1
- package/dist/ui/input-error.js.map +1 -1
- package/dist/ui/input-otp.js.map +1 -1
- package/dist/ui/link.js.map +1 -1
- package/dist/ui/modal.js.map +1 -1
- package/dist/ui/password-input.js.map +1 -1
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/section.js +4 -2
- package/dist/ui/section.js.map +1 -1
- package/dist/ui/segmented-control.js.map +1 -1
- package/dist/ui/segmented-pills.js.map +1 -1
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/text.js.map +1 -1
- package/dist/ui/tooltip.js.map +1 -1
- package/dist/vite-typescript-refresh.js.map +1 -1
- package/dist/vite.js.map +1 -1
- package/dist-standalone/chunks/chart-view-ZCTbih8A.js +59 -0
- package/dist-standalone/chunks/date-picker-field-CCnkf4SC.js +1 -0
- package/dist-standalone/chunks/dist-CK9gk4iB.js +1 -0
- package/dist-standalone/chunks/dist-DqlcM-vw.js +2 -0
- package/dist-standalone/chunks/icon-button-DcP25cn4.js +41 -0
- package/dist-standalone/chunks/instance-t58Awajh.js +1 -0
- package/dist-standalone/chunks/jsx-runtime-CN5ucv1d.js +1 -0
- package/dist-standalone/chunks/locale-CgtcxthU.js +1 -0
- package/dist-standalone/chunks/materialize-CWqnSEHR.js +1 -0
- package/dist-standalone/chunks/{notifications-echo-DsfNc4Ge.js → notifications-echo-uU87iJAV.js} +1 -1
- package/dist-standalone/chunks/number-BvVKQqOG.js +1 -0
- package/dist-standalone/chunks/page-props-B4GewgLI.js +1 -0
- package/dist-standalone/chunks/react-SIfiwpqq.js +1 -0
- package/dist-standalone/chunks/rich-editor-field-BtbU5XFS.js +158 -0
- package/dist-standalone/chunks/shared-props-B_wT1GcG.js +1 -0
- package/dist-standalone/chunks/subscriptions-BdHDnVA3.js +1 -0
- package/dist-standalone/chunks/time-picker-DSs9fDWe.js +1 -0
- package/dist-standalone/chunks/timezone-BukvzD0d.js +1 -0
- package/dist-standalone/chunks/translatable-DLw4h3x8.js +1 -0
- package/dist-standalone/chunks/use-effect-dispatcher-CiWYRvsF.js +97 -0
- package/dist-standalone/chunks/{with-selector-BwDoCrJJ.js → with-selector-zFUY-tQj.js} +1 -1
- package/dist-standalone/lattice.css +2 -2
- package/dist-standalone/lattice.js +4 -48
- package/dist-standalone/manifest.json +24 -15
- package/dist-standalone/sprite.svg +1 -1
- package/package.json +6 -6
- package/resources/icons/align-center.svg +1 -1
- package/resources/icons/align-justify.svg +1 -1
- package/resources/icons/align-left.svg +1 -1
- package/resources/icons/align-right.svg +1 -1
- package/resources/icons/arrow-down.svg +1 -1
- package/resources/icons/arrow-up.svg +1 -1
- package/resources/icons/bell.svg +1 -1
- package/resources/icons/bold.svg +1 -1
- package/resources/icons/calendar.svg +5 -5
- package/resources/icons/check.svg +1 -1
- package/resources/icons/chevron-down.svg +1 -1
- package/resources/icons/chevron-left.svg +1 -1
- package/resources/icons/chevron-right.svg +1 -1
- package/resources/icons/chevrons-up-down.svg +1 -1
- package/resources/icons/circle-alert.svg +1 -1
- package/resources/icons/circle-check.svg +1 -1
- package/resources/icons/circle-help.svg +1 -1
- package/resources/icons/circle-x.svg +1 -1
- package/resources/icons/clock.svg +1 -1
- package/resources/icons/code-xml.svg +1 -1
- package/resources/icons/code.svg +1 -1
- package/resources/icons/columns-3.svg +1 -1
- package/resources/icons/copy.svg +1 -1
- package/resources/icons/external-link.svg +1 -1
- package/resources/icons/eye-off.svg +1 -1
- package/resources/icons/eye.svg +1 -1
- package/resources/icons/filter.svg +1 -1
- package/resources/icons/heading-1.svg +1 -1
- package/resources/icons/heading-2.svg +1 -1
- package/resources/icons/heading-3.svg +1 -1
- package/resources/icons/heading.svg +1 -1
- package/resources/icons/highlighter.svg +1 -1
- package/resources/icons/info.svg +1 -1
- package/resources/icons/italic.svg +1 -1
- package/resources/icons/layout-dashboard.svg +1 -1
- package/resources/icons/link.svg +1 -1
- package/resources/icons/list-ordered.svg +1 -1
- package/resources/icons/list.svg +1 -1
- package/resources/icons/loader-2.svg +1 -1
- package/resources/icons/minus.svg +1 -1
- package/resources/icons/more-horizontal.svg +1 -1
- package/resources/icons/panel-left.svg +1 -1
- package/resources/icons/pencil-line.svg +1 -1
- package/resources/icons/pencil.svg +1 -1
- package/resources/icons/plus.svg +1 -1
- package/resources/icons/quote.svg +1 -1
- package/resources/icons/rotate-ccw.svg +1 -1
- package/resources/icons/rows-3.svg +1 -1
- package/resources/icons/search.svg +1 -1
- package/resources/icons/send.svg +1 -1
- package/resources/icons/settings.svg +1 -1
- package/resources/icons/smile.svg +1 -1
- package/resources/icons/strikethrough.svg +1 -1
- package/resources/icons/table.svg +1 -1
- package/resources/icons/trash-2.svg +1 -1
- package/resources/icons/underline.svg +1 -1
- package/resources/icons/x.svg +1 -1
- package/dist-standalone/chunks/chart-view-CpYsLvzR.js +0 -36
- package/dist-standalone/chunks/date-picker-field-lX8N40Ii.js +0 -1
- package/dist-standalone/chunks/dist-PaT1gYi_.js +0 -2
- package/dist-standalone/chunks/jsx-runtime-Drll_-DD.js +0 -1
- package/dist-standalone/chunks/locale-CXqr7LPR.js +0 -1
- package/dist-standalone/chunks/page-props-ClpVjpOc.js +0 -1
- package/dist-standalone/chunks/react-B8IZ02wI.js +0 -1
- package/dist-standalone/chunks/rich-editor-field-C71csVJv.js +0 -154
- package/dist-standalone/chunks/subscriptions-B1STcwPE.js +0 -1
- package/dist-standalone/chunks/use-effect-dispatcher-I8So0l_I.js +0 -97
|
@@ -9,7 +9,7 @@ function conditionFields(conditions) {
|
|
|
9
9
|
]) for (const condition of group ?? []) fields.add(condition.field);
|
|
10
10
|
return Array.from(fields);
|
|
11
11
|
}
|
|
12
|
-
var BOOLEAN_TRUE_VALUES = new Set([
|
|
12
|
+
var BOOLEAN_TRUE_VALUES = /* @__PURE__ */ new Set([
|
|
13
13
|
"1",
|
|
14
14
|
"true",
|
|
15
15
|
"on",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conditions.js","names":[],"sources":["../../../resources/js/form/lib/conditions.ts"],"sourcesContent":["import type { Condition, FieldConditions, Op } from \"@lattice-php/lattice/types/generated\";\n\nexport type { Condition, FieldConditions };\n\ntype FieldFlags = {\n hidden?: boolean;\n required?: boolean;\n readOnly?: boolean;\n disabled?: boolean;\n};\n\nexport type FieldState = {\n hidden: boolean;\n required: boolean;\n readOnly: boolean;\n disabled: boolean;\n};\n\nexport function conditionFields(conditions: Partial<FieldConditions> | undefined | null): string[] {\n const fields = new Set<string>();\n\n for (const group of [\n conditions?.visible,\n conditions?.required,\n conditions?.readOnly,\n conditions?.disabled,\n ]) {\n for (const condition of group ?? []) {\n fields.add(condition.field);\n }\n }\n\n return Array.from(fields);\n}\n\nconst BOOLEAN_TRUE_VALUES = new Set([\"1\", \"true\", \"on\", \"yes\"]);\n\n// Mirrors PHP filter_var(FILTER_VALIDATE_BOOLEAN) so conditions evaluate\n// identically on the server and the client.\nexport function toBoolean(value: unknown): boolean {\n if (typeof value === \"boolean\") {\n return value;\n }\n\n if (typeof value === \"number\") {\n return value === 1;\n }\n\n return BOOLEAN_TRUE_VALUES.has(String(value).toLowerCase());\n}\n\nfunction equals(actual: unknown, expected: unknown): boolean {\n if (typeof expected === \"boolean\") {\n return toBoolean(actual) === expected;\n }\n return String(actual ?? \"\") === String(expected ?? \"\");\n}\n\nfunction isIn(actual: unknown, expected: unknown): boolean {\n const needles = (Array.isArray(expected) ? expected : [expected]).map((value) => String(value));\n return needles.includes(String(actual ?? \"\"));\n}\n\nfunction isBlank(value: unknown): boolean {\n return value == null || String(value).trim() === \"\";\n}\n\n// Null when either value can't be parsed, so before/after never matches a bad date. Mirrors PHP strtotime.\nfunction compareDates(actual: unknown, expected: unknown): number | null {\n const left = Date.parse(String(actual));\n const right = Date.parse(String(expected));\n\n if (Number.isNaN(left) || Number.isNaN(right)) {\n return null;\n }\n\n return left === right ? 0 : left < right ? -1 : 1;\n}\n\n// Unknown operators from untrusted payloads fail open (the condition matches).\n// The `never` parameter makes an Op value added without a case above a\n// compile error rather than a silent fall-through.\nfunction evaluateUnknownOperator(_operator: never): boolean {\n return true;\n}\n\nfunction evaluateOp(operator: Op, actual: unknown, expected: unknown): boolean {\n switch (operator) {\n case \"eq\":\n return equals(actual, expected);\n case \"neq\":\n return !equals(actual, expected);\n case \"gt\":\n return Number(actual) > Number(expected);\n case \"lt\":\n return Number(actual) < Number(expected);\n case \"gte\":\n return Number(actual) >= Number(expected);\n case \"lte\":\n return Number(actual) <= Number(expected);\n case \"contains\":\n return String(actual ?? \"\").includes(String(expected ?? \"\"));\n case \"starts_with\":\n return String(actual ?? \"\").startsWith(String(expected ?? \"\"));\n case \"ends_with\":\n return String(actual ?? \"\").endsWith(String(expected ?? \"\"));\n case \"in\":\n return isIn(actual, expected);\n case \"not_in\":\n return !isIn(actual, expected);\n case \"before\":\n return compareDates(actual, expected) === -1;\n case \"after\":\n return compareDates(actual, expected) === 1;\n case \"empty\":\n return isBlank(actual);\n case \"filled\":\n return !isBlank(actual);\n default:\n return evaluateUnknownOperator(operator);\n }\n}\n\nfunction allMatch(conditions: Condition[], values: Record<string, unknown>): boolean {\n return conditions.every((condition) =>\n evaluateOp(condition.operator, values[condition.field], condition.value),\n );\n}\n\nfunction anyMatch(conditions: Condition[] | undefined, values: Record<string, unknown>): boolean {\n return Boolean(\n conditions?.some((condition) =>\n evaluateOp(condition.operator, values[condition.field], condition.value),\n ),\n );\n}\n\nexport function evaluateConditions(\n conditions: Partial<FieldConditions> | undefined,\n values: Record<string, unknown>,\n flags: FieldFlags,\n): FieldState {\n const visible = !conditions?.visible?.length || allMatch(conditions.visible, values);\n\n return {\n hidden: Boolean(flags.hidden) || !visible,\n required: Boolean(flags.required) || anyMatch(conditions?.required, values),\n readOnly: Boolean(flags.readOnly) || anyMatch(conditions?.readOnly, values),\n disabled: Boolean(flags.disabled) || anyMatch(conditions?.disabled, values),\n };\n}\n"],"mappings":";AAkBA,SAAgB,gBAAgB,YAAmE;CACjG,MAAM,yBAAS,IAAI,IAAY;CAE/B,KAAK,MAAM,SAAS;EAClB,YAAY;EACZ,YAAY;EACZ,YAAY;EACZ,YAAY;CACd,GACE,KAAK,MAAM,aAAa,SAAS,CAAC,GAChC,OAAO,IAAI,UAAU,KAAK;CAI9B,OAAO,MAAM,KAAK,MAAM;AAC1B;AAEA,IAAM,
|
|
1
|
+
{"version":3,"file":"conditions.js","names":[],"sources":["../../../resources/js/form/lib/conditions.ts"],"sourcesContent":["import type { Condition, FieldConditions, Op } from \"@lattice-php/lattice/types/generated\";\n\nexport type { Condition, FieldConditions };\n\ntype FieldFlags = {\n hidden?: boolean;\n required?: boolean;\n readOnly?: boolean;\n disabled?: boolean;\n};\n\nexport type FieldState = {\n hidden: boolean;\n required: boolean;\n readOnly: boolean;\n disabled: boolean;\n};\n\nexport function conditionFields(conditions: Partial<FieldConditions> | undefined | null): string[] {\n const fields = new Set<string>();\n\n for (const group of [\n conditions?.visible,\n conditions?.required,\n conditions?.readOnly,\n conditions?.disabled,\n ]) {\n for (const condition of group ?? []) {\n fields.add(condition.field);\n }\n }\n\n return Array.from(fields);\n}\n\nconst BOOLEAN_TRUE_VALUES = new Set([\"1\", \"true\", \"on\", \"yes\"]);\n\n// Mirrors PHP filter_var(FILTER_VALIDATE_BOOLEAN) so conditions evaluate\n// identically on the server and the client.\nexport function toBoolean(value: unknown): boolean {\n if (typeof value === \"boolean\") {\n return value;\n }\n\n if (typeof value === \"number\") {\n return value === 1;\n }\n\n return BOOLEAN_TRUE_VALUES.has(String(value).toLowerCase());\n}\n\nfunction equals(actual: unknown, expected: unknown): boolean {\n if (typeof expected === \"boolean\") {\n return toBoolean(actual) === expected;\n }\n return String(actual ?? \"\") === String(expected ?? \"\");\n}\n\nfunction isIn(actual: unknown, expected: unknown): boolean {\n const needles = (Array.isArray(expected) ? expected : [expected]).map((value) => String(value));\n return needles.includes(String(actual ?? \"\"));\n}\n\nfunction isBlank(value: unknown): boolean {\n return value == null || String(value).trim() === \"\";\n}\n\n// Null when either value can't be parsed, so before/after never matches a bad date. Mirrors PHP strtotime.\nfunction compareDates(actual: unknown, expected: unknown): number | null {\n const left = Date.parse(String(actual));\n const right = Date.parse(String(expected));\n\n if (Number.isNaN(left) || Number.isNaN(right)) {\n return null;\n }\n\n return left === right ? 0 : left < right ? -1 : 1;\n}\n\n// Unknown operators from untrusted payloads fail open (the condition matches).\n// The `never` parameter makes an Op value added without a case above a\n// compile error rather than a silent fall-through.\nfunction evaluateUnknownOperator(_operator: never): boolean {\n return true;\n}\n\nfunction evaluateOp(operator: Op, actual: unknown, expected: unknown): boolean {\n switch (operator) {\n case \"eq\":\n return equals(actual, expected);\n case \"neq\":\n return !equals(actual, expected);\n case \"gt\":\n return Number(actual) > Number(expected);\n case \"lt\":\n return Number(actual) < Number(expected);\n case \"gte\":\n return Number(actual) >= Number(expected);\n case \"lte\":\n return Number(actual) <= Number(expected);\n case \"contains\":\n return String(actual ?? \"\").includes(String(expected ?? \"\"));\n case \"starts_with\":\n return String(actual ?? \"\").startsWith(String(expected ?? \"\"));\n case \"ends_with\":\n return String(actual ?? \"\").endsWith(String(expected ?? \"\"));\n case \"in\":\n return isIn(actual, expected);\n case \"not_in\":\n return !isIn(actual, expected);\n case \"before\":\n return compareDates(actual, expected) === -1;\n case \"after\":\n return compareDates(actual, expected) === 1;\n case \"empty\":\n return isBlank(actual);\n case \"filled\":\n return !isBlank(actual);\n default:\n return evaluateUnknownOperator(operator);\n }\n}\n\nfunction allMatch(conditions: Condition[], values: Record<string, unknown>): boolean {\n return conditions.every((condition) =>\n evaluateOp(condition.operator, values[condition.field], condition.value),\n );\n}\n\nfunction anyMatch(conditions: Condition[] | undefined, values: Record<string, unknown>): boolean {\n return Boolean(\n conditions?.some((condition) =>\n evaluateOp(condition.operator, values[condition.field], condition.value),\n ),\n );\n}\n\nexport function evaluateConditions(\n conditions: Partial<FieldConditions> | undefined,\n values: Record<string, unknown>,\n flags: FieldFlags,\n): FieldState {\n const visible = !conditions?.visible?.length || allMatch(conditions.visible, values);\n\n return {\n hidden: Boolean(flags.hidden) || !visible,\n required: Boolean(flags.required) || anyMatch(conditions?.required, values),\n readOnly: Boolean(flags.readOnly) || anyMatch(conditions?.readOnly, values),\n disabled: Boolean(flags.disabled) || anyMatch(conditions?.disabled, values),\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-dom-name.js","names":[],"sources":["../../../resources/js/form/lib/field-dom-name.ts"],"sourcesContent":["export function fieldDomName(name: string, prefix?: string): string {\n if (!prefix) {\n return name;\n }\n\n const suffix = name.replace(/[^A-Za-z0-9_-]+/g, \"-\").replace(/^-+|-+$/g, \"\");\n\n return suffix ? `${prefix}-${suffix}` : prefix;\n}\n"],"mappings":";AAAA,SAAgB,aAAa,MAAc,QAAyB;CAClE,IAAI,CAAC,QACH,OAAO;CAGT,MAAM,SAAS,KAAK,QAAQ,oBAAoB,GAAG,
|
|
1
|
+
{"version":3,"file":"field-dom-name.js","names":[],"sources":["../../../resources/js/form/lib/field-dom-name.ts"],"sourcesContent":["export function fieldDomName(name: string, prefix?: string): string {\n if (!prefix) {\n return name;\n }\n\n const suffix = name.replace(/[^A-Za-z0-9_-]+/g, \"-\").replace(/^-+|-+$/g, \"\");\n\n return suffix ? `${prefix}-${suffix}` : prefix;\n}\n"],"mappings":";AAAA,SAAgB,aAAa,MAAc,QAAyB;CAClE,IAAI,CAAC,QACH,OAAO;CAGT,MAAM,SAAS,KAAK,QAAQ,oBAAoB,GAAG,CAAC,CAAC,QAAQ,YAAY,EAAE;CAE3E,OAAO,SAAS,GAAG,OAAO,GAAG,WAAW;AAC1C"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* descend into their child schemas as top-level fields; children live under
|
|
5
5
|
* `name.<index>.` paths instead.
|
|
6
6
|
*/
|
|
7
|
-
var ROW_FIELD_TYPES = new Set(["field.builder", "field.repeater"]);
|
|
7
|
+
var ROW_FIELD_TYPES = /* @__PURE__ */ new Set(["field.builder", "field.repeater"]);
|
|
8
8
|
function fieldProps(node) {
|
|
9
9
|
return node.props;
|
|
10
10
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-props.js","names":[],"sources":["../../../resources/js/form/lib/field-props.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport type { ComponentPropsMap } from \"@lattice-php/lattice/types/generated\";\n\n/**\n * The props every form-field node shares (the PHP Field base). Nodes flow through\n * the form framework loosely typed via the generic schema, so this is the typed\n * lens the shared hooks read them through. Everything is optional because the\n * lens is also applied to non-field nodes while walking the schema. Derived from\n * a generated field type (every field bakes the base in) rather than hand-written.\n */\ntype FieldProps = Partial<\n Pick<\n ComponentPropsMap[\"field.text-input\"],\n | \"conditions\"\n | \"dependsOnAny\"\n | \"dependsOnKeys\"\n | \"disabled\"\n | \"editablePrefill\"\n | \"helperText\"\n | \"label\"\n | \"name\"\n | \"prefillRefreshOn\"\n | \"prefillResetOn\"\n | \"readOnly\"\n | \"required\"\n | \"tooltip\"\n | \"value\"\n >\n>;\n\n/**\n * Field types whose value is a collection of rows. Schema walkers must not\n * descend into their child schemas as top-level fields; children live under\n * `name.<index>.` paths instead.\n */\nexport const ROW_FIELD_TYPES = new Set([\"field.builder\", \"field.repeater\"]);\n\nexport function fieldProps(node: Node): FieldProps {\n return node.props as FieldProps;\n}\n\nexport function walkFields(\n nodes: Node[] | undefined,\n visit: (props: FieldProps, node: Node) => void,\n): void {\n for (const child of nodes ?? []) {\n visit(fieldProps(child), child);\n walkFields(child.schema, visit);\n }\n}\n"],"mappings":";;;;;;AAmCA,IAAa,
|
|
1
|
+
{"version":3,"file":"field-props.js","names":[],"sources":["../../../resources/js/form/lib/field-props.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport type { ComponentPropsMap } from \"@lattice-php/lattice/types/generated\";\n\n/**\n * The props every form-field node shares (the PHP Field base). Nodes flow through\n * the form framework loosely typed via the generic schema, so this is the typed\n * lens the shared hooks read them through. Everything is optional because the\n * lens is also applied to non-field nodes while walking the schema. Derived from\n * a generated field type (every field bakes the base in) rather than hand-written.\n */\ntype FieldProps = Partial<\n Pick<\n ComponentPropsMap[\"field.text-input\"],\n | \"conditions\"\n | \"dependsOnAny\"\n | \"dependsOnKeys\"\n | \"disabled\"\n | \"editablePrefill\"\n | \"helperText\"\n | \"label\"\n | \"name\"\n | \"prefillRefreshOn\"\n | \"prefillResetOn\"\n | \"readOnly\"\n | \"required\"\n | \"tooltip\"\n | \"value\"\n >\n>;\n\n/**\n * Field types whose value is a collection of rows. Schema walkers must not\n * descend into their child schemas as top-level fields; children live under\n * `name.<index>.` paths instead.\n */\nexport const ROW_FIELD_TYPES = new Set([\"field.builder\", \"field.repeater\"]);\n\nexport function fieldProps(node: Node): FieldProps {\n return node.props as FieldProps;\n}\n\nexport function walkFields(\n nodes: Node[] | undefined,\n visit: (props: FieldProps, node: Node) => void,\n): void {\n for (const child of nodes ?? []) {\n visit(fieldProps(child), child);\n walkFields(child.schema, visit);\n }\n}\n"],"mappings":";;;;;;AAmCA,IAAa,kCAAkB,IAAI,IAAI,CAAC,iBAAiB,gBAAgB,CAAC;AAE1E,SAAgB,WAAW,MAAwB;CACjD,OAAO,KAAK;AACd;AAEA,SAAgB,WACd,OACA,OACM;CACN,KAAK,MAAM,SAAS,SAAS,CAAC,GAAG;EAC/B,MAAM,WAAW,KAAK,GAAG,KAAK;EAC9B,WAAW,MAAM,QAAQ,KAAK;CAChC;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-path.js","names":[],"sources":["../../../resources/js/form/lib/form-path.ts"],"sourcesContent":["function pathParts(path: string): string[] {\n return path.split(\".\").filter((part) => part !== \"\");\n}\n\nexport function appendPath(\n base: string | null | undefined,\n ...parts: Array<string | number>\n): string {\n const suffix = parts.map(String).filter((part) => part !== \"\");\n\n return [base ?? \"\", ...suffix].filter((part) => part !== \"\").join(\".\");\n}\n\nexport function toHtmlName(path: string): string {\n const [head, ...tail] = pathParts(path);\n\n return tail.reduce((name, part) => `${name}[${part}]`, head ?? \"\");\n}\n\nexport function getPath(values: Record<string, unknown>, path: string): unknown {\n let current: unknown = values;\n\n for (const part of pathParts(path)) {\n if (current == null) {\n return undefined;\n }\n\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\nfunction emptyContainer(nextPart: string | undefined): Record<string, unknown> | unknown[] {\n return nextPart !== undefined && /^\\d+$/.test(nextPart) ? [] : {};\n}\n\nexport function setPath(\n values: Record<string, unknown>,\n path: string,\n value: unknown,\n): Record<string, unknown> {\n const parts = pathParts(path);\n\n if (parts.length === 0) {\n return values;\n }\n\n const write = (current: unknown, index: number): unknown => {\n const part = parts[index];\n const last = index === parts.length - 1;\n const source =\n current && typeof current === \"object\" ? current : emptyContainer(parts[index + 1]);\n const next = Array.isArray(source) ? [...source] : { ...(source as Record<string, unknown>) };\n\n (next as Record<string, unknown>)[part] = last\n ? value\n : write((source as Record<string, unknown>)[part], index + 1);\n\n return next;\n };\n\n return write(values, 0) as Record<string, unknown>;\n}\n"],"mappings":";AAAA,SAAS,UAAU,MAAwB;CACzC,OAAO,KAAK,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"form-path.js","names":[],"sources":["../../../resources/js/form/lib/form-path.ts"],"sourcesContent":["function pathParts(path: string): string[] {\n return path.split(\".\").filter((part) => part !== \"\");\n}\n\nexport function appendPath(\n base: string | null | undefined,\n ...parts: Array<string | number>\n): string {\n const suffix = parts.map(String).filter((part) => part !== \"\");\n\n return [base ?? \"\", ...suffix].filter((part) => part !== \"\").join(\".\");\n}\n\nexport function toHtmlName(path: string): string {\n const [head, ...tail] = pathParts(path);\n\n return tail.reduce((name, part) => `${name}[${part}]`, head ?? \"\");\n}\n\nexport function getPath(values: Record<string, unknown>, path: string): unknown {\n let current: unknown = values;\n\n for (const part of pathParts(path)) {\n if (current == null) {\n return undefined;\n }\n\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\nfunction emptyContainer(nextPart: string | undefined): Record<string, unknown> | unknown[] {\n return nextPart !== undefined && /^\\d+$/.test(nextPart) ? [] : {};\n}\n\nexport function setPath(\n values: Record<string, unknown>,\n path: string,\n value: unknown,\n): Record<string, unknown> {\n const parts = pathParts(path);\n\n if (parts.length === 0) {\n return values;\n }\n\n const write = (current: unknown, index: number): unknown => {\n const part = parts[index];\n const last = index === parts.length - 1;\n const source =\n current && typeof current === \"object\" ? current : emptyContainer(parts[index + 1]);\n const next = Array.isArray(source) ? [...source] : { ...(source as Record<string, unknown>) };\n\n (next as Record<string, unknown>)[part] = last\n ? value\n : write((source as Record<string, unknown>)[part], index + 1);\n\n return next;\n };\n\n return write(values, 0) as Record<string, unknown>;\n}\n"],"mappings":";AAAA,SAAS,UAAU,MAAwB;CACzC,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,QAAQ,SAAS,SAAS,EAAE;AACrD;AAEA,SAAgB,WACd,MACA,GAAG,OACK;CACR,MAAM,SAAS,MAAM,IAAI,MAAM,CAAC,CAAC,QAAQ,SAAS,SAAS,EAAE;CAE7D,OAAO,CAAC,QAAQ,IAAI,GAAG,MAAM,CAAC,CAAC,QAAQ,SAAS,SAAS,EAAE,CAAC,CAAC,KAAK,GAAG;AACvE;AAEA,SAAgB,WAAW,MAAsB;CAC/C,MAAM,CAAC,MAAM,GAAG,QAAQ,UAAU,IAAI;CAEtC,OAAO,KAAK,QAAQ,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,IAAI,QAAQ,EAAE;AACnE;AAEA,SAAgB,QAAQ,QAAiC,MAAuB;CAC9E,IAAI,UAAmB;CAEvB,KAAK,MAAM,QAAQ,UAAU,IAAI,GAAG;EAClC,IAAI,WAAW,MACb;EAGF,UAAW,QAAoC;CACjD;CAEA,OAAO;AACT;AAEA,SAAS,eAAe,UAAmE;CACzF,OAAO,aAAa,KAAA,KAAa,QAAQ,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC;AAClE;AAEA,SAAgB,QACd,QACA,MACA,OACyB;CACzB,MAAM,QAAQ,UAAU,IAAI;CAE5B,IAAI,MAAM,WAAW,GACnB,OAAO;CAGT,MAAM,SAAS,SAAkB,UAA2B;EAC1D,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,UAAU,MAAM,SAAS;EACtC,MAAM,SACJ,WAAW,OAAO,YAAY,WAAW,UAAU,eAAe,MAAM,QAAQ,EAAE;EACpF,MAAM,OAAO,MAAM,QAAQ,MAAM,IAAI,CAAC,GAAG,MAAM,IAAI,EAAE,GAAI,OAAmC;EAE5F,KAAkC,QAAQ,OACtC,QACA,MAAO,OAAmC,OAAO,QAAQ,CAAC;EAE9D,OAAO;CACT;CAEA,OAAO,MAAM,QAAQ,CAAC;AACxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-transport.js","names":[],"sources":["../../../resources/js/form/lib/form-transport.ts"],"sourcesContent":["/**\n * Shared client transport for the lattice form endpoint: every form sub-action\n * (validation resolve, option search) POSTs to the same signed URL, so the\n * request shape lives here once.\n */\n\nimport { apiFetch } from \"@lattice-php/lattice/core/api\";\n\nexport const FORM_DEBOUNCE_MS = 250;\n\nexport function postFormAction<T>(\n action: string,\n componentRef: string,\n body: Record<string, unknown>,\n signal: AbortSignal,\n): Promise<T | null> {\n return apiFetch(action, {\n method: \"POST\",\n ref: componentRef,\n signal,\n body: JSON.stringify(body),\n throwOnError: false,\n }).then((response) => (response.ok ? (response.json() as Promise<T>) : null));\n}\n"],"mappings":";;;;;;;AAQA,IAAa,mBAAmB;AAEhC,SAAgB,eACd,QACA,cACA,MACA,QACmB;CACnB,OAAO,SAAS,QAAQ;EACtB,QAAQ;EACR,KAAK;EACL;EACA,MAAM,KAAK,UAAU,IAAI;EACzB,cAAc;CAChB,CAAC,
|
|
1
|
+
{"version":3,"file":"form-transport.js","names":[],"sources":["../../../resources/js/form/lib/form-transport.ts"],"sourcesContent":["/**\n * Shared client transport for the lattice form endpoint: every form sub-action\n * (validation resolve, option search) POSTs to the same signed URL, so the\n * request shape lives here once.\n */\n\nimport { apiFetch } from \"@lattice-php/lattice/core/api\";\n\nexport const FORM_DEBOUNCE_MS = 250;\n\nexport function postFormAction<T>(\n action: string,\n componentRef: string,\n body: Record<string, unknown>,\n signal: AbortSignal,\n): Promise<T | null> {\n return apiFetch(action, {\n method: \"POST\",\n ref: componentRef,\n signal,\n body: JSON.stringify(body),\n throwOnError: false,\n }).then((response) => (response.ok ? (response.json() as Promise<T>) : null));\n}\n"],"mappings":";;;;;;;AAQA,IAAa,mBAAmB;AAEhC,SAAgB,eACd,QACA,cACA,MACA,QACmB;CACnB,OAAO,SAAS,QAAQ;EACtB,QAAQ;EACR,KAAK;EACL;EACA,MAAM,KAAK,UAAU,IAAI;EACzB,cAAc;CAChB,CAAC,CAAC,CAAC,MAAM,aAAc,SAAS,KAAM,SAAS,KAAK,IAAmB,IAAK;AAC9E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefill-targets.js","names":[],"sources":["../../../resources/js/form/lib/prefill-targets.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport { fieldProps, ROW_FIELD_TYPES } from \"./field-props\";\nimport { rowSchemaFor } from \"@lattice-php/lattice/form/components/fields/row-templates\";\nimport { appendPath, getPath } from \"./form-path\";\nimport { buildOverrideKey, rowIdFrom } from \"./override-keys\";\n\ntype PrefillTarget = {\n path: string;\n overrideKey: string;\n resetOn: string[];\n refreshOn: string[];\n};\n\ntype PrefillSnapshot = {\n targets: PrefillTarget[];\n values: Record<string, unknown>;\n};\n\nexport { getPath } from \"./form-path\";\n\nfunction mapDep(dep: string, rowPath: string | null): string {\n if (dep.startsWith(\"@\")) {\n return dep.slice(1);\n }\n\n return rowPath === null ? dep : appendPath(rowPath, dep);\n}\n\nfunction targetFor(\n node: Node,\n rowPath: string | null,\n identityCollectionPath: string | null,\n index = 0,\n row: Record<string, unknown> = {},\n): PrefillTarget | null {\n const props = fieldProps(node);\n\n if (!props.editablePrefill || !props.name) {\n return null;\n }\n\n const rowId = rowIdFrom(row);\n\n return {\n path: rowPath === null ? props.name : appendPath(rowPath, props.name),\n overrideKey:\n identityCollectionPath === null\n ? props.name\n : buildOverrideKey(identityCollectionPath, rowId, index, props.name),\n resetOn: (props.prefillResetOn ?? []).map((dep) => mapDep(dep, rowPath)),\n refreshOn: (props.prefillRefreshOn ?? []).map((dep) => mapDep(dep, rowPath)),\n };\n}\n\nexport function collectPrefillTargets(\n nodes: Node[] | undefined,\n values: Record<string, unknown>,\n): PrefillTarget[] {\n const targets: PrefillTarget[] = [];\n\n const walk = (\n list: Node[] | undefined,\n rowPath: string | null = null,\n identityRowPath: string | null = null,\n identityCollectionPath: string | null = null,\n index = 0,\n row: Record<string, unknown> = {},\n ): void => {\n for (const node of list ?? []) {\n if (ROW_FIELD_TYPES.has(node.type)) {\n const name = fieldProps(node).name;\n if (name) {\n const childCollectionPath = appendPath(rowPath, name);\n const childIdentityCollectionPath = appendPath(identityRowPath, name);\n const storedRows = getPath(values, childCollectionPath);\n const rows = Array.isArray(storedRows)\n ? (storedRows as Array<Record<string, unknown>>)\n : [];\n rows.forEach((childRow, childIndex) => {\n walk(\n rowSchemaFor(node, childRow),\n appendPath(childCollectionPath, childIndex),\n appendPath(childIdentityCollectionPath, rowIdFrom(childRow) ?? childIndex),\n childIdentityCollectionPath,\n childIndex,\n childRow,\n );\n });\n }\n\n continue;\n }\n\n const target = targetFor(node, rowPath, identityCollectionPath, index, row);\n if (target) {\n targets.push(target);\n }\n\n walk(node.schema, rowPath, identityRowPath, identityCollectionPath, index, row);\n }\n };\n\n walk(nodes);\n\n return targets;\n}\n\nexport function pathsToClear(previous: PrefillSnapshot, next: PrefillSnapshot): string[] {\n const previousByKey = new Map(\n previous.targets.map((target) => [target.overrideKey, target] as const),\n );\n\n return next.targets\n .filter((target) => {\n const previousTarget = previousByKey.get(target.overrideKey);\n\n return target.resetOn.some((dep, index) => {\n const previousDep = previousTarget?.resetOn[index] ?? dep;\n\n return !Object.is(getPath(previous.values, previousDep), getPath(next.values, dep));\n });\n })\n .map((target) => target.overrideKey);\n}\n\nexport function seededOverrides(\n targets: PrefillTarget[],\n values: Record<string, unknown>,\n): string[] {\n return targets\n .filter((target) => {\n const value = getPath(values, target.path);\n\n return value !== undefined && value !== null && value !== \"\";\n })\n .map((target) => target.overrideKey);\n}\n\nexport function pruneOverrides(overrides: Set<string>, targets: PrefillTarget[]): Set<string> {\n const liveKeys = new Set(targets.map((target) => target.overrideKey));\n\n return new Set([...overrides].filter((key) => liveKeys.has(key)));\n}\n"],"mappings":";;;;;AAoBA,SAAS,OAAO,KAAa,SAAgC;CAC3D,IAAI,IAAI,WAAW,GAAG,GACpB,OAAO,IAAI,MAAM,CAAC;CAGpB,OAAO,YAAY,OAAO,MAAM,WAAW,SAAS,GAAG;AACzD;AAEA,SAAS,UACP,MACA,SACA,wBACA,QAAQ,GACR,MAA+B,CAAC,GACV;CACtB,MAAM,QAAQ,WAAW,IAAI;CAE7B,IAAI,CAAC,MAAM,mBAAmB,CAAC,MAAM,MACnC,OAAO;CAGT,MAAM,QAAQ,UAAU,GAAG;CAE3B,OAAO;EACL,MAAM,YAAY,OAAO,MAAM,OAAO,WAAW,SAAS,MAAM,IAAI;EACpE,aACE,2BAA2B,OACvB,MAAM,OACN,iBAAiB,wBAAwB,OAAO,OAAO,MAAM,IAAI;EACvE,UAAU,MAAM,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"prefill-targets.js","names":[],"sources":["../../../resources/js/form/lib/prefill-targets.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport { fieldProps, ROW_FIELD_TYPES } from \"./field-props\";\nimport { rowSchemaFor } from \"@lattice-php/lattice/form/components/fields/row-templates\";\nimport { appendPath, getPath } from \"./form-path\";\nimport { buildOverrideKey, rowIdFrom } from \"./override-keys\";\n\ntype PrefillTarget = {\n path: string;\n overrideKey: string;\n resetOn: string[];\n refreshOn: string[];\n};\n\ntype PrefillSnapshot = {\n targets: PrefillTarget[];\n values: Record<string, unknown>;\n};\n\nexport { getPath } from \"./form-path\";\n\nfunction mapDep(dep: string, rowPath: string | null): string {\n if (dep.startsWith(\"@\")) {\n return dep.slice(1);\n }\n\n return rowPath === null ? dep : appendPath(rowPath, dep);\n}\n\nfunction targetFor(\n node: Node,\n rowPath: string | null,\n identityCollectionPath: string | null,\n index = 0,\n row: Record<string, unknown> = {},\n): PrefillTarget | null {\n const props = fieldProps(node);\n\n if (!props.editablePrefill || !props.name) {\n return null;\n }\n\n const rowId = rowIdFrom(row);\n\n return {\n path: rowPath === null ? props.name : appendPath(rowPath, props.name),\n overrideKey:\n identityCollectionPath === null\n ? props.name\n : buildOverrideKey(identityCollectionPath, rowId, index, props.name),\n resetOn: (props.prefillResetOn ?? []).map((dep) => mapDep(dep, rowPath)),\n refreshOn: (props.prefillRefreshOn ?? []).map((dep) => mapDep(dep, rowPath)),\n };\n}\n\nexport function collectPrefillTargets(\n nodes: Node[] | undefined,\n values: Record<string, unknown>,\n): PrefillTarget[] {\n const targets: PrefillTarget[] = [];\n\n const walk = (\n list: Node[] | undefined,\n rowPath: string | null = null,\n identityRowPath: string | null = null,\n identityCollectionPath: string | null = null,\n index = 0,\n row: Record<string, unknown> = {},\n ): void => {\n for (const node of list ?? []) {\n if (ROW_FIELD_TYPES.has(node.type)) {\n const name = fieldProps(node).name;\n if (name) {\n const childCollectionPath = appendPath(rowPath, name);\n const childIdentityCollectionPath = appendPath(identityRowPath, name);\n const storedRows = getPath(values, childCollectionPath);\n const rows = Array.isArray(storedRows)\n ? (storedRows as Array<Record<string, unknown>>)\n : [];\n rows.forEach((childRow, childIndex) => {\n walk(\n rowSchemaFor(node, childRow),\n appendPath(childCollectionPath, childIndex),\n appendPath(childIdentityCollectionPath, rowIdFrom(childRow) ?? childIndex),\n childIdentityCollectionPath,\n childIndex,\n childRow,\n );\n });\n }\n\n continue;\n }\n\n const target = targetFor(node, rowPath, identityCollectionPath, index, row);\n if (target) {\n targets.push(target);\n }\n\n walk(node.schema, rowPath, identityRowPath, identityCollectionPath, index, row);\n }\n };\n\n walk(nodes);\n\n return targets;\n}\n\nexport function pathsToClear(previous: PrefillSnapshot, next: PrefillSnapshot): string[] {\n const previousByKey = new Map(\n previous.targets.map((target) => [target.overrideKey, target] as const),\n );\n\n return next.targets\n .filter((target) => {\n const previousTarget = previousByKey.get(target.overrideKey);\n\n return target.resetOn.some((dep, index) => {\n const previousDep = previousTarget?.resetOn[index] ?? dep;\n\n return !Object.is(getPath(previous.values, previousDep), getPath(next.values, dep));\n });\n })\n .map((target) => target.overrideKey);\n}\n\nexport function seededOverrides(\n targets: PrefillTarget[],\n values: Record<string, unknown>,\n): string[] {\n return targets\n .filter((target) => {\n const value = getPath(values, target.path);\n\n return value !== undefined && value !== null && value !== \"\";\n })\n .map((target) => target.overrideKey);\n}\n\nexport function pruneOverrides(overrides: Set<string>, targets: PrefillTarget[]): Set<string> {\n const liveKeys = new Set(targets.map((target) => target.overrideKey));\n\n return new Set([...overrides].filter((key) => liveKeys.has(key)));\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wizard-steps.js","names":[],"sources":["../../../resources/js/form/lib/wizard-steps.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport { errorKeyBelongsTo } from \"./field-errors\";\nimport { fieldProps, ROW_FIELD_TYPES } from \"./field-props\";\n\nexport function stepFieldNames(step: Node): string[] {\n const names: string[] = [];\n\n const collect = (node: Node): void => {\n const name = fieldProps(node).name;\n\n if (name) {\n names.push(name);\n }\n if (name && ROW_FIELD_TYPES.has(node.type)) {\n return;\n }\n for (const child of node.schema ?? []) {\n collect(child);\n }\n };\n\n for (const child of step.schema ?? []) {\n collect(child);\n }\n\n return names;\n}\n\nexport function stepValidationPaths(step: Node): string[] {\n const paths: string[] = [];\n\n const expand = (node: Node): void => {\n const name = fieldProps(node).name;\n\n if (name) {\n paths.push(name, `${name}.*`);\n }\n\n if (name && ROW_FIELD_TYPES.has(node.type)) {\n for (const child of stepFieldNames(node)) {\n paths.push(`${name}.*.${child}`);\n }\n\n return;\n }\n\n for (const child of node.schema ?? []) {\n expand(child);\n }\n };\n\n for (const child of step.schema ?? []) {\n expand(child);\n }\n\n return paths;\n}\n\nexport function stepsWithErrors(\n stepNames: string[][],\n errors: Record<string, string | undefined>,\n): Set<number> {\n const keys = Object.keys(errors).filter((key) => Boolean(errors[key]));\n const owners = new Set<number>();\n\n stepNames.forEach((names, index) => {\n const owns = keys.some((key) => names.some((name) => errorKeyBelongsTo(key, name)));\n\n if (owns) {\n owners.add(index);\n }\n });\n\n return owners;\n}\n\nexport function firstErroredStep(\n stepNames: string[][],\n errors: Record<string, string | undefined>,\n): number | null {\n const owners = stepsWithErrors(stepNames, errors);\n\n return owners.size > 0 ? Math.min(...owners) : null;\n}\n"],"mappings":";;;AAIA,SAAgB,eAAe,MAAsB;CACnD,MAAM,QAAkB,CAAC;CAEzB,MAAM,WAAW,SAAqB;EACpC,MAAM,OAAO,WAAW,IAAI,
|
|
1
|
+
{"version":3,"file":"wizard-steps.js","names":[],"sources":["../../../resources/js/form/lib/wizard-steps.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport { errorKeyBelongsTo } from \"./field-errors\";\nimport { fieldProps, ROW_FIELD_TYPES } from \"./field-props\";\n\nexport function stepFieldNames(step: Node): string[] {\n const names: string[] = [];\n\n const collect = (node: Node): void => {\n const name = fieldProps(node).name;\n\n if (name) {\n names.push(name);\n }\n if (name && ROW_FIELD_TYPES.has(node.type)) {\n return;\n }\n for (const child of node.schema ?? []) {\n collect(child);\n }\n };\n\n for (const child of step.schema ?? []) {\n collect(child);\n }\n\n return names;\n}\n\nexport function stepValidationPaths(step: Node): string[] {\n const paths: string[] = [];\n\n const expand = (node: Node): void => {\n const name = fieldProps(node).name;\n\n if (name) {\n paths.push(name, `${name}.*`);\n }\n\n if (name && ROW_FIELD_TYPES.has(node.type)) {\n for (const child of stepFieldNames(node)) {\n paths.push(`${name}.*.${child}`);\n }\n\n return;\n }\n\n for (const child of node.schema ?? []) {\n expand(child);\n }\n };\n\n for (const child of step.schema ?? []) {\n expand(child);\n }\n\n return paths;\n}\n\nexport function stepsWithErrors(\n stepNames: string[][],\n errors: Record<string, string | undefined>,\n): Set<number> {\n const keys = Object.keys(errors).filter((key) => Boolean(errors[key]));\n const owners = new Set<number>();\n\n stepNames.forEach((names, index) => {\n const owns = keys.some((key) => names.some((name) => errorKeyBelongsTo(key, name)));\n\n if (owns) {\n owners.add(index);\n }\n });\n\n return owners;\n}\n\nexport function firstErroredStep(\n stepNames: string[][],\n errors: Record<string, string | undefined>,\n): number | null {\n const owners = stepsWithErrors(stepNames, errors);\n\n return owners.size > 0 ? Math.min(...owners) : null;\n}\n"],"mappings":";;;AAIA,SAAgB,eAAe,MAAsB;CACnD,MAAM,QAAkB,CAAC;CAEzB,MAAM,WAAW,SAAqB;EACpC,MAAM,OAAO,WAAW,IAAI,CAAC,CAAC;EAE9B,IAAI,MACF,MAAM,KAAK,IAAI;EAEjB,IAAI,QAAQ,gBAAgB,IAAI,KAAK,IAAI,GACvC;EAEF,KAAK,MAAM,SAAS,KAAK,UAAU,CAAC,GAClC,QAAQ,KAAK;CAEjB;CAEA,KAAK,MAAM,SAAS,KAAK,UAAU,CAAC,GAClC,QAAQ,KAAK;CAGf,OAAO;AACT;AAEA,SAAgB,oBAAoB,MAAsB;CACxD,MAAM,QAAkB,CAAC;CAEzB,MAAM,UAAU,SAAqB;EACnC,MAAM,OAAO,WAAW,IAAI,CAAC,CAAC;EAE9B,IAAI,MACF,MAAM,KAAK,MAAM,GAAG,KAAK,GAAG;EAG9B,IAAI,QAAQ,gBAAgB,IAAI,KAAK,IAAI,GAAG;GAC1C,KAAK,MAAM,SAAS,eAAe,IAAI,GACrC,MAAM,KAAK,GAAG,KAAK,KAAK,OAAO;GAGjC;EACF;EAEA,KAAK,MAAM,SAAS,KAAK,UAAU,CAAC,GAClC,OAAO,KAAK;CAEhB;CAEA,KAAK,MAAM,SAAS,KAAK,UAAU,CAAC,GAClC,OAAO,KAAK;CAGd,OAAO;AACT;AAEA,SAAgB,gBACd,WACA,QACa;CACb,MAAM,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,QAAQ,QAAQ,QAAQ,OAAO,IAAI,CAAC;CACrE,MAAM,yBAAS,IAAI,IAAY;CAE/B,UAAU,SAAS,OAAO,UAAU;EAGlC,IAFa,KAAK,MAAM,QAAQ,MAAM,MAAM,SAAS,kBAAkB,KAAK,IAAI,CAAC,CAE7E,GACF,OAAO,IAAI,KAAK;CAEpB,CAAC;CAED,OAAO;AACT;AAEA,SAAgB,iBACd,WACA,QACe;CACf,MAAM,SAAS,gBAAgB,WAAW,MAAM;CAEhD,OAAO,OAAO,OAAO,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI;AACjD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtins.js","names":[],"sources":["../../../resources/js/form/rich-editor/builtins.tsx"],"sourcesContent":["import { Details, DetailsContent, DetailsSummary } from \"@tiptap/extension-details\";\nimport { Highlight } from \"@tiptap/extension-highlight\";\nimport { TableKit } from \"@tiptap/extension-table\";\nimport { TextAlign } from \"@tiptap/extension-text-align\";\nimport type { Editor } from \"@tiptap/core\";\nimport type { StarterKitOptions } from \"@tiptap/starter-kit\";\nimport { useState } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@lattice-php/lattice/ui/dropdown-menu\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@lattice-php/lattice/ui/popover\";\nimport { seedRichEditorExtension, type ToolbarButton } from \"./registry\";\nimport { ToolbarIconButton } from \"./toolbar-button\";\n\ntype HeadingLevels = NonNullable<Exclude<StarterKitOptions[\"heading\"], false>[\"levels\"]>;\n\nconst ALL_HEADING_LEVELS = [1, 2, 3, 4, 5, 6];\n\nconst ALL_ALIGNMENTS = [\"left\", \"center\", \"right\", \"justify\"];\n\nconst DEFAULT_EMOJIS = [\n \"😀\",\n \"😅\",\n \"😂\",\n \"🥳\",\n \"😎\",\n \"🤔\",\n \"👍\",\n \"🙏\",\n \"🔥\",\n \"🎉\",\n \"🚀\",\n \"💡\",\n \"✅\",\n \"❌\",\n \"⭐\",\n \"❤️\",\n];\n\nfunction headingLevels(levels: number[] | undefined): HeadingLevels {\n const valid = (levels ?? ALL_HEADING_LEVELS).filter((level) => level >= 1 && level <= 6);\n\n return (valid.length > 0 ? valid : ALL_HEADING_LEVELS) as HeadingLevels;\n}\n\nfunction HeadingMenu({ editor, levels }: { editor: Editor; levels: number[] }) {\n const { t } = useT(\"lattice\");\n const label = t(\"form.editor.heading\", \"Heading\");\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <ToolbarIconButton\n active={editor.isActive(\"heading\")}\n icon=\"heading\"\n label={label}\n testId=\"editor-heading\"\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"min-w-32\">\n {levels.map((level) => (\n <DropdownMenuItem\n className={cn(\n editor.isActive(\"heading\", { level }) && \"bg-lt-accent text-lt-accent-fg\",\n )}\n data-test={`editor-heading-${level}`}\n key={level}\n onClick={() =>\n editor\n .chain()\n .focus()\n .toggleHeading({ level: level as HeadingLevels[number] })\n .run()\n }\n >\n {t(`form.editor.heading-${level}`, `Heading ${level}`)}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nfunction LinkControl({ editor }: { editor: Editor }) {\n const { t } = useT(\"lattice\");\n const [open, setOpen] = useState(false);\n const [url, setUrl] = useState(\"\");\n\n const apply = () => {\n if (url) {\n editor.chain().focus().extendMarkRange(\"link\").setLink({ href: url }).run();\n } else {\n editor.chain().focus().extendMarkRange(\"link\").unsetLink().run();\n }\n\n setOpen(false);\n };\n\n return (\n <Popover\n onOpenChange={(next) => {\n if (next) {\n setUrl((editor.getAttributes(\"link\").href as string | undefined) ?? \"\");\n }\n\n setOpen(next);\n }}\n open={open}\n >\n <PopoverTrigger asChild>\n <ToolbarIconButton\n active={editor.isActive(\"link\")}\n icon=\"link\"\n label={t(\"form.editor.link\", \"Link\")}\n testId=\"editor-link\"\n />\n </PopoverTrigger>\n <PopoverContent className=\"flex w-72 items-center gap-1 p-2\">\n <input\n aria-label={t(\"form.editor.link-url\", \"Link URL\")}\n className=\"h-7 min-w-0 flex-1 rounded-lt-sm border border-lt-input bg-transparent px-2 text-sm outline-none focus:border-lt-ring\"\n data-test=\"editor-link-url\"\n onChange={(event) => setUrl(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n apply();\n }\n }}\n placeholder=\"https://\"\n type=\"url\"\n value={url}\n />\n <ToolbarIconButton\n icon=\"check\"\n label={t(\"form.editor.link-apply\", \"Apply link\")}\n onClick={apply}\n testId=\"editor-link-apply\"\n />\n {editor.isActive(\"link\") && (\n <ToolbarIconButton\n icon=\"trash-2\"\n label={t(\"form.editor.link-remove\", \"Remove link\")}\n onClick={() => {\n editor.chain().focus().extendMarkRange(\"link\").unsetLink().run();\n setOpen(false);\n }}\n testId=\"editor-link-remove\"\n />\n )}\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction EmojiPicker({ editor, emojis }: { editor: Editor; emojis: string[] }) {\n const { t } = useT(\"lattice\");\n const [open, setOpen] = useState(false);\n\n return (\n <Popover onOpenChange={setOpen} open={open}>\n <PopoverTrigger asChild>\n <ToolbarIconButton\n icon=\"smile\"\n label={t(\"form.editor.insert-emoji\", \"Insert emoji\")}\n testId=\"editor-emoji\"\n />\n </PopoverTrigger>\n <PopoverContent className=\"grid grid-cols-8 gap-0.5 p-1\">\n {emojis.map((emoji) => (\n <button\n className=\"inline-flex size-7 items-center justify-center rounded-lt-sm text-base hover:bg-lt-accent\"\n key={emoji}\n onClick={() => {\n editor.chain().focus().insertContent(emoji).run();\n setOpen(false);\n }}\n onMouseDown={(event) => event.preventDefault()}\n type=\"button\"\n >\n {emoji}\n </button>\n ))}\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction markButton(key: string, icon: string, label: string, mark: string): ToolbarButton {\n return {\n icon,\n key,\n label,\n isActive: (editor) => editor.isActive(mark),\n run: (editor) => editor.chain().focus().toggleMark(mark).run(),\n };\n}\n\nlet registered = false;\n\n/**\n * Called by the editor field when its chunk loads. Registration must be an\n * explicitly invoked export: the package ships side-effect-free modules, so a\n * bare `import \"./builtins\"` would be tree-shaken out of production builds.\n */\nexport function registerBuiltinRichEditorExtensions(): void {\n if (registered) {\n return;\n }\n\n registered = true;\n\n seedRichEditorExtension(\"bold\", {\n group: \"marks\",\n starterKit: () => ({ bold: {} }),\n toolbar: () => [markButton(\"bold\", \"bold\", \"Bold\", \"bold\")],\n });\n\n seedRichEditorExtension(\"italic\", {\n group: \"marks\",\n starterKit: () => ({ italic: {} }),\n toolbar: () => [markButton(\"italic\", \"italic\", \"Italic\", \"italic\")],\n });\n\n seedRichEditorExtension(\"strike\", {\n group: \"marks\",\n starterKit: () => ({ strike: {} }),\n toolbar: () => [markButton(\"strikethrough\", \"strikethrough\", \"Strikethrough\", \"strike\")],\n });\n\n seedRichEditorExtension(\"underline\", {\n group: \"marks\",\n starterKit: () => ({ underline: {} }),\n toolbar: () => [markButton(\"underline\", \"underline\", \"Underline\", \"underline\")],\n });\n\n seedRichEditorExtension(\"highlight\", {\n group: \"marks\",\n extensions: () => [Highlight],\n toolbar: () => [markButton(\"highlight\", \"highlighter\", \"Highlight\", \"highlight\")],\n });\n\n seedRichEditorExtension(\"code\", {\n group: \"marks\",\n starterKit: () => ({ code: {} }),\n toolbar: () => [markButton(\"code\", \"code-xml\", \"Code\", \"code\")],\n });\n\n seedRichEditorExtension(\"heading\", {\n starterKit: (props) => ({ heading: { levels: headingLevels(props.levels) } }),\n toolbar: (props) => {\n const levels = headingLevels(props.levels);\n\n return [\n {\n key: \"heading\",\n component: ({ editor }) => <HeadingMenu editor={editor} levels={levels} />,\n },\n ];\n },\n });\n\n seedRichEditorExtension(\"bullet-list\", {\n group: \"blocks\",\n starterKit: () => ({ bulletList: {}, listItem: {} }),\n toolbar: () => [\n {\n icon: \"list\",\n key: \"bullet-list\",\n label: \"Bullet list\",\n isActive: (editor) => editor.isActive(\"bulletList\"),\n run: (editor) => editor.chain().focus().toggleBulletList().run(),\n },\n ],\n });\n\n seedRichEditorExtension(\"ordered-list\", {\n group: \"blocks\",\n starterKit: () => ({ orderedList: {}, listItem: {} }),\n toolbar: () => [\n {\n icon: \"list-ordered\",\n key: \"ordered-list\",\n label: \"Ordered list\",\n isActive: (editor) => editor.isActive(\"orderedList\"),\n run: (editor) => editor.chain().focus().toggleOrderedList().run(),\n },\n ],\n });\n\n seedRichEditorExtension(\"blockquote\", {\n group: \"blocks\",\n starterKit: () => ({ blockquote: {} }),\n toolbar: () => [\n {\n icon: \"quote\",\n key: \"blockquote\",\n label: \"Blockquote\",\n isActive: (editor) => editor.isActive(\"blockquote\"),\n run: (editor) => editor.chain().focus().toggleBlockquote().run(),\n },\n ],\n });\n\n seedRichEditorExtension(\"code-block\", {\n group: \"blocks\",\n starterKit: () => ({ codeBlock: {} }),\n toolbar: () => [\n {\n icon: \"code\",\n key: \"code-block\",\n label: \"Code block\",\n isActive: (editor) => editor.isActive(\"codeBlock\"),\n run: (editor) => editor.chain().focus().toggleCodeBlock().run(),\n },\n ],\n });\n\n seedRichEditorExtension(\"horizontal-rule\", {\n group: \"blocks\",\n starterKit: () => ({ horizontalRule: {} }),\n toolbar: () => [\n {\n icon: \"minus\",\n key: \"horizontal-rule\",\n label: \"Horizontal rule\",\n isActive: () => false,\n run: (editor) => editor.chain().focus().setHorizontalRule().run(),\n },\n ],\n });\n\n const ALIGNMENT_BUTTONS: Record<string, { icon: string; key: string; label: string }> = {\n left: { icon: \"align-left\", key: \"align-left\", label: \"Align left\" },\n center: { icon: \"align-center\", key: \"align-center\", label: \"Align center\" },\n right: { icon: \"align-right\", key: \"align-right\", label: \"Align right\" },\n justify: { icon: \"align-justify\", key: \"justify\", label: \"Justify\" },\n };\n\n seedRichEditorExtension(\"text-align\", {\n extensions: (props) => [\n TextAlign.configure({\n alignments: props.alignments ?? ALL_ALIGNMENTS,\n types: [\"heading\", \"paragraph\"],\n }),\n ],\n toolbar: (props) =>\n (props.alignments ?? ALL_ALIGNMENTS)\n .filter((alignment) => alignment in ALIGNMENT_BUTTONS)\n .map((alignment) => ({\n ...ALIGNMENT_BUTTONS[alignment],\n isActive: (editor: Editor) => editor.isActive({ textAlign: alignment }),\n run: (editor: Editor) => editor.chain().focus().setTextAlign(alignment).run(),\n })),\n });\n\n seedRichEditorExtension(\"link\", {\n starterKit: (props) => ({\n link: {\n openOnClick: props.openOnClick ?? false,\n ...(props.protocols ? { protocols: props.protocols } : {}),\n },\n }),\n toolbar: () => [\n {\n key: \"link\",\n component: ({ editor }) => <LinkControl editor={editor} />,\n },\n ],\n });\n\n seedRichEditorExtension(\"table\", {\n group: \"insert\",\n extensions: () => [TableKit.configure({ table: { resizable: false } })],\n toolbar: (props) => [\n {\n icon: \"table\",\n key: \"insert-table\",\n label: \"Insert table\",\n isActive: (editor) => editor.isActive(\"table\"),\n run: (editor) =>\n editor\n .chain()\n .focus()\n .insertTable({\n rows: props.rows ?? 3,\n cols: props.cols ?? 3,\n withHeaderRow: props.withHeaderRow ?? true,\n })\n .run(),\n },\n {\n icon: \"columns-3\",\n key: \"add-column\",\n label: \"Add column\",\n isActive: () => false,\n isDisabled: (editor) => !editor.can().addColumnAfter(),\n run: (editor) => editor.chain().focus().addColumnAfter().run(),\n },\n {\n icon: \"rows-3\",\n key: \"add-row\",\n label: \"Add row\",\n isActive: () => false,\n isDisabled: (editor) => !editor.can().addRowAfter(),\n run: (editor) => editor.chain().focus().addRowAfter().run(),\n },\n {\n icon: \"trash-2\",\n key: \"delete-table\",\n label: \"Delete table\",\n isActive: () => false,\n isDisabled: (editor) => !editor.can().deleteTable(),\n run: (editor) => editor.chain().focus().deleteTable().run(),\n },\n ],\n });\n\n seedRichEditorExtension(\"details\", {\n group: \"insert\",\n extensions: () => [Details, DetailsSummary, DetailsContent],\n toolbar: () => [\n {\n icon: \"chevron-right\",\n key: \"details\",\n label: \"Details\",\n isActive: (editor) => editor.isActive(\"details\"),\n run: (editor) => {\n if (editor.isActive(\"details\")) {\n editor.chain().focus().unsetDetails().run();\n\n return;\n }\n\n editor.chain().focus().setDetails().run();\n },\n },\n ],\n });\n\n seedRichEditorExtension(\"emoji\", {\n toolbar: (props) => {\n const emojis = props.emojis ?? DEFAULT_EMOJIS;\n\n return [\n {\n key: \"insert-emoji\",\n component: ({ editor }) => <EmojiPicker editor={editor} emojis={emojis} />,\n },\n ];\n },\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"builtins.js","names":[],"sources":["../../../resources/js/form/rich-editor/builtins.tsx"],"sourcesContent":["import { Details, DetailsContent, DetailsSummary } from \"@tiptap/extension-details\";\nimport { Highlight } from \"@tiptap/extension-highlight\";\nimport { TableKit } from \"@tiptap/extension-table\";\nimport { TextAlign } from \"@tiptap/extension-text-align\";\nimport type { Editor } from \"@tiptap/core\";\nimport type { StarterKitOptions } from \"@tiptap/starter-kit\";\nimport { useState } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@lattice-php/lattice/ui/dropdown-menu\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@lattice-php/lattice/ui/popover\";\nimport { seedRichEditorExtension, type ToolbarButton } from \"./registry\";\nimport { ToolbarIconButton } from \"./toolbar-button\";\n\ntype HeadingLevels = NonNullable<Exclude<StarterKitOptions[\"heading\"], false>[\"levels\"]>;\n\nconst ALL_HEADING_LEVELS = [1, 2, 3, 4, 5, 6];\n\nconst ALL_ALIGNMENTS = [\"left\", \"center\", \"right\", \"justify\"];\n\nconst DEFAULT_EMOJIS = [\n \"😀\",\n \"😅\",\n \"😂\",\n \"🥳\",\n \"😎\",\n \"🤔\",\n \"👍\",\n \"🙏\",\n \"🔥\",\n \"🎉\",\n \"🚀\",\n \"💡\",\n \"✅\",\n \"❌\",\n \"⭐\",\n \"❤️\",\n];\n\nfunction headingLevels(levels: number[] | undefined): HeadingLevels {\n const valid = (levels ?? ALL_HEADING_LEVELS).filter((level) => level >= 1 && level <= 6);\n\n return (valid.length > 0 ? valid : ALL_HEADING_LEVELS) as HeadingLevels;\n}\n\nfunction HeadingMenu({ editor, levels }: { editor: Editor; levels: number[] }) {\n const { t } = useT(\"lattice\");\n const label = t(\"form.editor.heading\", \"Heading\");\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <ToolbarIconButton\n active={editor.isActive(\"heading\")}\n icon=\"heading\"\n label={label}\n testId=\"editor-heading\"\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"min-w-32\">\n {levels.map((level) => (\n <DropdownMenuItem\n className={cn(\n editor.isActive(\"heading\", { level }) && \"bg-lt-accent text-lt-accent-fg\",\n )}\n data-test={`editor-heading-${level}`}\n key={level}\n onClick={() =>\n editor\n .chain()\n .focus()\n .toggleHeading({ level: level as HeadingLevels[number] })\n .run()\n }\n >\n {t(`form.editor.heading-${level}`, `Heading ${level}`)}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nfunction LinkControl({ editor }: { editor: Editor }) {\n const { t } = useT(\"lattice\");\n const [open, setOpen] = useState(false);\n const [url, setUrl] = useState(\"\");\n\n const apply = () => {\n if (url) {\n editor.chain().focus().extendMarkRange(\"link\").setLink({ href: url }).run();\n } else {\n editor.chain().focus().extendMarkRange(\"link\").unsetLink().run();\n }\n\n setOpen(false);\n };\n\n return (\n <Popover\n onOpenChange={(next) => {\n if (next) {\n setUrl((editor.getAttributes(\"link\").href as string | undefined) ?? \"\");\n }\n\n setOpen(next);\n }}\n open={open}\n >\n <PopoverTrigger asChild>\n <ToolbarIconButton\n active={editor.isActive(\"link\")}\n icon=\"link\"\n label={t(\"form.editor.link\", \"Link\")}\n testId=\"editor-link\"\n />\n </PopoverTrigger>\n <PopoverContent className=\"flex w-72 items-center gap-1 p-2\">\n <input\n aria-label={t(\"form.editor.link-url\", \"Link URL\")}\n className=\"h-7 min-w-0 flex-1 rounded-lt-sm border border-lt-input bg-transparent px-2 text-sm outline-none focus:border-lt-ring\"\n data-test=\"editor-link-url\"\n onChange={(event) => setUrl(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n apply();\n }\n }}\n placeholder=\"https://\"\n type=\"url\"\n value={url}\n />\n <ToolbarIconButton\n icon=\"check\"\n label={t(\"form.editor.link-apply\", \"Apply link\")}\n onClick={apply}\n testId=\"editor-link-apply\"\n />\n {editor.isActive(\"link\") && (\n <ToolbarIconButton\n icon=\"trash-2\"\n label={t(\"form.editor.link-remove\", \"Remove link\")}\n onClick={() => {\n editor.chain().focus().extendMarkRange(\"link\").unsetLink().run();\n setOpen(false);\n }}\n testId=\"editor-link-remove\"\n />\n )}\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction EmojiPicker({ editor, emojis }: { editor: Editor; emojis: string[] }) {\n const { t } = useT(\"lattice\");\n const [open, setOpen] = useState(false);\n\n return (\n <Popover onOpenChange={setOpen} open={open}>\n <PopoverTrigger asChild>\n <ToolbarIconButton\n icon=\"smile\"\n label={t(\"form.editor.insert-emoji\", \"Insert emoji\")}\n testId=\"editor-emoji\"\n />\n </PopoverTrigger>\n <PopoverContent className=\"grid grid-cols-8 gap-0.5 p-1\">\n {emojis.map((emoji) => (\n <button\n className=\"inline-flex size-7 items-center justify-center rounded-lt-sm text-base hover:bg-lt-accent\"\n key={emoji}\n onClick={() => {\n editor.chain().focus().insertContent(emoji).run();\n setOpen(false);\n }}\n onMouseDown={(event) => event.preventDefault()}\n type=\"button\"\n >\n {emoji}\n </button>\n ))}\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction markButton(key: string, icon: string, label: string, mark: string): ToolbarButton {\n return {\n icon,\n key,\n label,\n isActive: (editor) => editor.isActive(mark),\n run: (editor) => editor.chain().focus().toggleMark(mark).run(),\n };\n}\n\nlet registered = false;\n\n/**\n * Called by the editor field when its chunk loads. Registration must be an\n * explicitly invoked export: the package ships side-effect-free modules, so a\n * bare `import \"./builtins\"` would be tree-shaken out of production builds.\n */\nexport function registerBuiltinRichEditorExtensions(): void {\n if (registered) {\n return;\n }\n\n registered = true;\n\n seedRichEditorExtension(\"bold\", {\n group: \"marks\",\n starterKit: () => ({ bold: {} }),\n toolbar: () => [markButton(\"bold\", \"bold\", \"Bold\", \"bold\")],\n });\n\n seedRichEditorExtension(\"italic\", {\n group: \"marks\",\n starterKit: () => ({ italic: {} }),\n toolbar: () => [markButton(\"italic\", \"italic\", \"Italic\", \"italic\")],\n });\n\n seedRichEditorExtension(\"strike\", {\n group: \"marks\",\n starterKit: () => ({ strike: {} }),\n toolbar: () => [markButton(\"strikethrough\", \"strikethrough\", \"Strikethrough\", \"strike\")],\n });\n\n seedRichEditorExtension(\"underline\", {\n group: \"marks\",\n starterKit: () => ({ underline: {} }),\n toolbar: () => [markButton(\"underline\", \"underline\", \"Underline\", \"underline\")],\n });\n\n seedRichEditorExtension(\"highlight\", {\n group: \"marks\",\n extensions: () => [Highlight],\n toolbar: () => [markButton(\"highlight\", \"highlighter\", \"Highlight\", \"highlight\")],\n });\n\n seedRichEditorExtension(\"code\", {\n group: \"marks\",\n starterKit: () => ({ code: {} }),\n toolbar: () => [markButton(\"code\", \"code-xml\", \"Code\", \"code\")],\n });\n\n seedRichEditorExtension(\"heading\", {\n starterKit: (props) => ({ heading: { levels: headingLevels(props.levels) } }),\n toolbar: (props) => {\n const levels = headingLevels(props.levels);\n\n return [\n {\n key: \"heading\",\n component: ({ editor }) => <HeadingMenu editor={editor} levels={levels} />,\n },\n ];\n },\n });\n\n seedRichEditorExtension(\"bullet-list\", {\n group: \"blocks\",\n starterKit: () => ({ bulletList: {}, listItem: {} }),\n toolbar: () => [\n {\n icon: \"list\",\n key: \"bullet-list\",\n label: \"Bullet list\",\n isActive: (editor) => editor.isActive(\"bulletList\"),\n run: (editor) => editor.chain().focus().toggleBulletList().run(),\n },\n ],\n });\n\n seedRichEditorExtension(\"ordered-list\", {\n group: \"blocks\",\n starterKit: () => ({ orderedList: {}, listItem: {} }),\n toolbar: () => [\n {\n icon: \"list-ordered\",\n key: \"ordered-list\",\n label: \"Ordered list\",\n isActive: (editor) => editor.isActive(\"orderedList\"),\n run: (editor) => editor.chain().focus().toggleOrderedList().run(),\n },\n ],\n });\n\n seedRichEditorExtension(\"blockquote\", {\n group: \"blocks\",\n starterKit: () => ({ blockquote: {} }),\n toolbar: () => [\n {\n icon: \"quote\",\n key: \"blockquote\",\n label: \"Blockquote\",\n isActive: (editor) => editor.isActive(\"blockquote\"),\n run: (editor) => editor.chain().focus().toggleBlockquote().run(),\n },\n ],\n });\n\n seedRichEditorExtension(\"code-block\", {\n group: \"blocks\",\n starterKit: () => ({ codeBlock: {} }),\n toolbar: () => [\n {\n icon: \"code\",\n key: \"code-block\",\n label: \"Code block\",\n isActive: (editor) => editor.isActive(\"codeBlock\"),\n run: (editor) => editor.chain().focus().toggleCodeBlock().run(),\n },\n ],\n });\n\n seedRichEditorExtension(\"horizontal-rule\", {\n group: \"blocks\",\n starterKit: () => ({ horizontalRule: {} }),\n toolbar: () => [\n {\n icon: \"minus\",\n key: \"horizontal-rule\",\n label: \"Horizontal rule\",\n isActive: () => false,\n run: (editor) => editor.chain().focus().setHorizontalRule().run(),\n },\n ],\n });\n\n const ALIGNMENT_BUTTONS: Record<string, { icon: string; key: string; label: string }> = {\n left: { icon: \"align-left\", key: \"align-left\", label: \"Align left\" },\n center: { icon: \"align-center\", key: \"align-center\", label: \"Align center\" },\n right: { icon: \"align-right\", key: \"align-right\", label: \"Align right\" },\n justify: { icon: \"align-justify\", key: \"justify\", label: \"Justify\" },\n };\n\n seedRichEditorExtension(\"text-align\", {\n extensions: (props) => [\n TextAlign.configure({\n alignments: props.alignments ?? ALL_ALIGNMENTS,\n types: [\"heading\", \"paragraph\"],\n }),\n ],\n toolbar: (props) =>\n (props.alignments ?? ALL_ALIGNMENTS)\n .filter((alignment) => alignment in ALIGNMENT_BUTTONS)\n .map((alignment) => ({\n ...ALIGNMENT_BUTTONS[alignment],\n isActive: (editor: Editor) => editor.isActive({ textAlign: alignment }),\n run: (editor: Editor) => editor.chain().focus().setTextAlign(alignment).run(),\n })),\n });\n\n seedRichEditorExtension(\"link\", {\n starterKit: (props) => ({\n link: {\n openOnClick: props.openOnClick ?? false,\n ...(props.protocols ? { protocols: props.protocols } : {}),\n },\n }),\n toolbar: () => [\n {\n key: \"link\",\n component: ({ editor }) => <LinkControl editor={editor} />,\n },\n ],\n });\n\n seedRichEditorExtension(\"table\", {\n group: \"insert\",\n extensions: () => [TableKit.configure({ table: { resizable: false } })],\n toolbar: (props) => [\n {\n icon: \"table\",\n key: \"insert-table\",\n label: \"Insert table\",\n isActive: (editor) => editor.isActive(\"table\"),\n run: (editor) =>\n editor\n .chain()\n .focus()\n .insertTable({\n rows: props.rows ?? 3,\n cols: props.cols ?? 3,\n withHeaderRow: props.withHeaderRow ?? true,\n })\n .run(),\n },\n {\n icon: \"columns-3\",\n key: \"add-column\",\n label: \"Add column\",\n isActive: () => false,\n isDisabled: (editor) => !editor.can().addColumnAfter(),\n run: (editor) => editor.chain().focus().addColumnAfter().run(),\n },\n {\n icon: \"rows-3\",\n key: \"add-row\",\n label: \"Add row\",\n isActive: () => false,\n isDisabled: (editor) => !editor.can().addRowAfter(),\n run: (editor) => editor.chain().focus().addRowAfter().run(),\n },\n {\n icon: \"trash-2\",\n key: \"delete-table\",\n label: \"Delete table\",\n isActive: () => false,\n isDisabled: (editor) => !editor.can().deleteTable(),\n run: (editor) => editor.chain().focus().deleteTable().run(),\n },\n ],\n });\n\n seedRichEditorExtension(\"details\", {\n group: \"insert\",\n extensions: () => [Details, DetailsSummary, DetailsContent],\n toolbar: () => [\n {\n icon: \"chevron-right\",\n key: \"details\",\n label: \"Details\",\n isActive: (editor) => editor.isActive(\"details\"),\n run: (editor) => {\n if (editor.isActive(\"details\")) {\n editor.chain().focus().unsetDetails().run();\n\n return;\n }\n\n editor.chain().focus().setDetails().run();\n },\n },\n ],\n });\n\n seedRichEditorExtension(\"emoji\", {\n toolbar: (props) => {\n const emojis = props.emojis ?? DEFAULT_EMOJIS;\n\n return [\n {\n key: \"insert-emoji\",\n component: ({ editor }) => <EmojiPicker editor={editor} emojis={emojis} />,\n },\n ];\n },\n });\n}\n"],"mappings":"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"}
|
|
@@ -10,4 +10,5 @@ export type DateConfig = {
|
|
|
10
10
|
year?: string | null;
|
|
11
11
|
};
|
|
12
12
|
export declare function formatDateValue(value: unknown, date: DateConfig, options?: FormatOptions): string;
|
|
13
|
+
export declare function toDate(value: unknown): Date | null;
|
|
13
14
|
export declare function preciseDateTime(value: unknown, options?: FormatOptions): string;
|
package/dist/format/date-time.js
CHANGED
|
@@ -9,6 +9,10 @@ function formatDateValue(value, date, options) {
|
|
|
9
9
|
if (date.year) intl.year = date.year;
|
|
10
10
|
return new Intl.DateTimeFormat(options?.locale, intl).format(parsed);
|
|
11
11
|
}
|
|
12
|
+
function toDate(value) {
|
|
13
|
+
const date = value instanceof Date ? value : typeof value === "string" || typeof value === "number" ? new Date(value) : null;
|
|
14
|
+
return date && !Number.isNaN(date.getTime()) ? date : null;
|
|
15
|
+
}
|
|
12
16
|
function preciseDateTime(value, options) {
|
|
13
17
|
const date = new Date(String(value));
|
|
14
18
|
if (Number.isNaN(date.getTime())) return "";
|
|
@@ -25,6 +29,6 @@ function preciseDateTime(value, options) {
|
|
|
25
29
|
return options?.timeZone ? `${formatted} (${options.timeZone})` : formatted;
|
|
26
30
|
}
|
|
27
31
|
//#endregion
|
|
28
|
-
export { formatDateValue, preciseDateTime };
|
|
32
|
+
export { formatDateValue, preciseDateTime, toDate };
|
|
29
33
|
|
|
30
34
|
//# sourceMappingURL=date-time.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-time.js","names":[],"sources":["../../resources/js/format/date-time.ts"],"sourcesContent":["import type { DateTimeStyle } from \"@lattice-php/lattice/types/generated\";\n\nexport type FormatOptions = {\n locale?: string;\n timeZone?: string;\n};\n\nexport type DateConfig = {\n dateStyle: DateTimeStyle | null;\n timeStyle: DateTimeStyle | null;\n month?: string | null;\n year?: string | null;\n};\n\nexport function formatDateValue(value: unknown, date: DateConfig, options?: FormatOptions): string {\n const parsed = new Date(String(value));\n\n if (Number.isNaN(parsed.getTime())) {\n return String(value ?? \"\");\n }\n\n const intl: Intl.DateTimeFormatOptions = { timeZone: options?.timeZone };\n\n if (date.dateStyle) {\n intl.dateStyle = date.dateStyle;\n }\n\n if (date.timeStyle) {\n intl.timeStyle = date.timeStyle;\n }\n\n if (date.month) {\n intl.month = date.month as Intl.DateTimeFormatOptions[\"month\"];\n }\n\n if (date.year) {\n intl.year = date.year as Intl.DateTimeFormatOptions[\"year\"];\n }\n\n return new Intl.DateTimeFormat(options?.locale, intl).format(parsed);\n}\n\nexport function preciseDateTime(value: unknown, options?: FormatOptions): string {\n const date = new Date(String(value));\n\n if (Number.isNaN(date.getTime())) {\n return \"\";\n }\n\n const formatted = new Intl.DateTimeFormat(options?.locale, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZone: options?.timeZone,\n timeZoneName: \"short\",\n }).format(date);\n\n return options?.timeZone ? `${formatted} (${options.timeZone})` : formatted;\n}\n"],"mappings":";AAcA,SAAgB,gBAAgB,OAAgB,MAAkB,SAAiC;CACjG,MAAM,SAAS,IAAI,KAAK,OAAO,KAAK,CAAC;CAErC,IAAI,OAAO,MAAM,OAAO,QAAQ,CAAC,GAC/B,OAAO,OAAO,SAAS,EAAE;CAG3B,MAAM,OAAmC,EAAE,UAAU,SAAS,SAAS;CAEvE,IAAI,KAAK,WACP,KAAK,YAAY,KAAK;CAGxB,IAAI,KAAK,WACP,KAAK,YAAY,KAAK;CAGxB,IAAI,KAAK,OACP,KAAK,QAAQ,KAAK;CAGpB,IAAI,KAAK,MACP,KAAK,OAAO,KAAK;CAGnB,OAAO,IAAI,KAAK,eAAe,SAAS,QAAQ,IAAI,
|
|
1
|
+
{"version":3,"file":"date-time.js","names":[],"sources":["../../resources/js/format/date-time.ts"],"sourcesContent":["import type { DateTimeStyle } from \"@lattice-php/lattice/types/generated\";\n\nexport type FormatOptions = {\n locale?: string;\n timeZone?: string;\n};\n\nexport type DateConfig = {\n dateStyle: DateTimeStyle | null;\n timeStyle: DateTimeStyle | null;\n month?: string | null;\n year?: string | null;\n};\n\nexport function formatDateValue(value: unknown, date: DateConfig, options?: FormatOptions): string {\n const parsed = new Date(String(value));\n\n if (Number.isNaN(parsed.getTime())) {\n return String(value ?? \"\");\n }\n\n const intl: Intl.DateTimeFormatOptions = { timeZone: options?.timeZone };\n\n if (date.dateStyle) {\n intl.dateStyle = date.dateStyle;\n }\n\n if (date.timeStyle) {\n intl.timeStyle = date.timeStyle;\n }\n\n if (date.month) {\n intl.month = date.month as Intl.DateTimeFormatOptions[\"month\"];\n }\n\n if (date.year) {\n intl.year = date.year as Intl.DateTimeFormatOptions[\"year\"];\n }\n\n return new Intl.DateTimeFormat(options?.locale, intl).format(parsed);\n}\n\nexport function toDate(value: unknown): Date | null {\n const date =\n value instanceof Date\n ? value\n : typeof value === \"string\" || typeof value === \"number\"\n ? new Date(value)\n : null;\n\n return date && !Number.isNaN(date.getTime()) ? date : null;\n}\n\nexport function preciseDateTime(value: unknown, options?: FormatOptions): string {\n const date = new Date(String(value));\n\n if (Number.isNaN(date.getTime())) {\n return \"\";\n }\n\n const formatted = new Intl.DateTimeFormat(options?.locale, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZone: options?.timeZone,\n timeZoneName: \"short\",\n }).format(date);\n\n return options?.timeZone ? `${formatted} (${options.timeZone})` : formatted;\n}\n"],"mappings":";AAcA,SAAgB,gBAAgB,OAAgB,MAAkB,SAAiC;CACjG,MAAM,SAAS,IAAI,KAAK,OAAO,KAAK,CAAC;CAErC,IAAI,OAAO,MAAM,OAAO,QAAQ,CAAC,GAC/B,OAAO,OAAO,SAAS,EAAE;CAG3B,MAAM,OAAmC,EAAE,UAAU,SAAS,SAAS;CAEvE,IAAI,KAAK,WACP,KAAK,YAAY,KAAK;CAGxB,IAAI,KAAK,WACP,KAAK,YAAY,KAAK;CAGxB,IAAI,KAAK,OACP,KAAK,QAAQ,KAAK;CAGpB,IAAI,KAAK,MACP,KAAK,OAAO,KAAK;CAGnB,OAAO,IAAI,KAAK,eAAe,SAAS,QAAQ,IAAI,CAAC,CAAC,OAAO,MAAM;AACrE;AAEA,SAAgB,OAAO,OAA6B;CAClD,MAAM,OACJ,iBAAiB,OACb,QACA,OAAO,UAAU,YAAY,OAAO,UAAU,WAC5C,IAAI,KAAK,KAAK,IACd;CAER,OAAO,QAAQ,CAAC,OAAO,MAAM,KAAK,QAAQ,CAAC,IAAI,OAAO;AACxD;AAEA,SAAgB,gBAAgB,OAAgB,SAAiC;CAC/E,MAAM,OAAO,IAAI,KAAK,OAAO,KAAK,CAAC;CAEnC,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,GAC7B,OAAO;CAGT,MAAM,YAAY,IAAI,KAAK,eAAe,SAAS,QAAQ;EACzD,MAAM;EACN,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,UAAU,SAAS;EACnB,cAAc;CAChB,CAAC,CAAC,CAAC,OAAO,IAAI;CAEd,OAAO,SAAS,WAAW,GAAG,UAAU,IAAI,QAAQ,SAAS,KAAK;AACpE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number.js","names":[],"sources":["../../resources/js/format/number.ts"],"sourcesContent":["import type { NumberFormat } from \"@lattice-php/lattice/types/generated\";\nimport { numericValue } from \"./numeric\";\n\nexport function formatNumber(value: unknown, format: NumberFormat, locale: string): string {\n const number = numericValue(value);\n\n if (number === null) {\n return String(value ?? \"\");\n }\n\n const options: Intl.NumberFormatOptions = {\n notation: format.notation as Intl.NumberFormatOptions[\"notation\"],\n minimumFractionDigits: format.minimumFractionDigits ?? undefined,\n maximumFractionDigits: format.maximumFractionDigits ?? undefined,\n };\n\n if (format.currency) {\n options.style = \"currency\";\n options.currency = format.currency;\n } else if (format.unit) {\n options.style = \"unit\";\n options.unit = format.unit;\n }\n\n return new Intl.NumberFormat(locale, options).format(number);\n}\n"],"mappings":";;AAGA,SAAgB,aAAa,OAAgB,QAAsB,QAAwB;CACzF,MAAM,SAAS,aAAa,KAAK;CAEjC,IAAI,WAAW,MACb,OAAO,OAAO,SAAS,EAAE;CAG3B,MAAM,UAAoC;EACxC,UAAU,OAAO;EACjB,uBAAuB,OAAO,yBAAyB,KAAA;EACvD,uBAAuB,OAAO,yBAAyB,KAAA;CACzD;CAEA,IAAI,OAAO,UAAU;EACnB,QAAQ,QAAQ;EAChB,QAAQ,WAAW,OAAO;CAC5B,OAAO,IAAI,OAAO,MAAM;EACtB,QAAQ,QAAQ;EAChB,QAAQ,OAAO,OAAO;CACxB;CAEA,OAAO,IAAI,KAAK,aAAa,QAAQ,OAAO,
|
|
1
|
+
{"version":3,"file":"number.js","names":[],"sources":["../../resources/js/format/number.ts"],"sourcesContent":["import type { NumberFormat } from \"@lattice-php/lattice/types/generated\";\nimport { numericValue } from \"./numeric\";\n\nexport function formatNumber(value: unknown, format: NumberFormat, locale: string): string {\n const number = numericValue(value);\n\n if (number === null) {\n return String(value ?? \"\");\n }\n\n const options: Intl.NumberFormatOptions = {\n notation: format.notation as Intl.NumberFormatOptions[\"notation\"],\n minimumFractionDigits: format.minimumFractionDigits ?? undefined,\n maximumFractionDigits: format.maximumFractionDigits ?? undefined,\n };\n\n if (format.currency) {\n options.style = \"currency\";\n options.currency = format.currency;\n } else if (format.unit) {\n options.style = \"unit\";\n options.unit = format.unit;\n }\n\n return new Intl.NumberFormat(locale, options).format(number);\n}\n"],"mappings":";;AAGA,SAAgB,aAAa,OAAgB,QAAsB,QAAwB;CACzF,MAAM,SAAS,aAAa,KAAK;CAEjC,IAAI,WAAW,MACb,OAAO,OAAO,SAAS,EAAE;CAG3B,MAAM,UAAoC;EACxC,UAAU,OAAO;EACjB,uBAAuB,OAAO,yBAAyB,KAAA;EACvD,uBAAuB,OAAO,yBAAyB,KAAA;CACzD;CAEA,IAAI,OAAO,UAAU;EACnB,QAAQ,QAAQ;EAChB,QAAQ,WAAW,OAAO;CAC5B,OAAO,IAAI,OAAO,MAAM;EACtB,QAAQ,QAAQ;EAChB,QAAQ,OAAO,OAAO;CACxB;CAEA,OAAO,IAAI,KAAK,aAAa,QAAQ,OAAO,CAAC,CAAC,OAAO,MAAM;AAC7D"}
|
package/dist/i18n/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"sources":["../../resources/js/i18n/config.ts"],"sourcesContent":["import type { I18nConfig } from \"@lattice-php/lattice/types/generated\";\nimport { useSyncExternalStore } from \"react\";\n\ntype Config = {\n readonly locales: readonly string[];\n readonly timezone: string | null;\n};\n\nconst fallback: Config = { locales: [], timezone: null };\nconst listeners = new Set<() => void>();\n\nlet active: Config = fallback;\n\nfunction normalizeLocales(locales: readonly string[] | undefined): string[] {\n return Array.from(new Set((locales ?? []).map((locale) => locale.trim()).filter(Boolean)));\n}\n\nfunction sameLocales(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((locale, index) => locale === right[index]);\n}\n\nfunction snapshot(): Config {\n return active;\n}\n\nfunction subscribe(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nfunction notify(): void {\n listeners.forEach((listener) => listener());\n}\n\nexport function setConfig(config: I18nConfig | undefined): void {\n const locales = normalizeLocales(config?.locales);\n const timezone = config?.timezone ?? null;\n\n if (sameLocales(active.locales, locales) && active.timezone === timezone) {\n return;\n }\n\n active = { locales, timezone };\n notify();\n}\n\nexport function configTimezone(): string | null {\n return active.timezone;\n}\n\nexport function subscribeConfig(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nexport function useConfig(): Config {\n return useSyncExternalStore(subscribe, snapshot, () => fallback);\n}\n"],"mappings":";;AAQA,IAAM,WAAmB;CAAE,SAAS,CAAC;CAAG,UAAU;AAAK;AACvD,IAAM,4BAAY,IAAI,IAAgB;AAEtC,IAAI,SAAiB;AAErB,SAAS,iBAAiB,SAAkD;CAC1E,OAAO,MAAM,KAAK,IAAI,KAAK,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../../resources/js/i18n/config.ts"],"sourcesContent":["import type { I18nConfig } from \"@lattice-php/lattice/types/generated\";\nimport { useSyncExternalStore } from \"react\";\n\ntype Config = {\n readonly locales: readonly string[];\n readonly timezone: string | null;\n};\n\nconst fallback: Config = { locales: [], timezone: null };\nconst listeners = new Set<() => void>();\n\nlet active: Config = fallback;\n\nfunction normalizeLocales(locales: readonly string[] | undefined): string[] {\n return Array.from(new Set((locales ?? []).map((locale) => locale.trim()).filter(Boolean)));\n}\n\nfunction sameLocales(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((locale, index) => locale === right[index]);\n}\n\nfunction snapshot(): Config {\n return active;\n}\n\nfunction subscribe(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nfunction notify(): void {\n listeners.forEach((listener) => listener());\n}\n\nexport function setConfig(config: I18nConfig | undefined): void {\n const locales = normalizeLocales(config?.locales);\n const timezone = config?.timezone ?? null;\n\n if (sameLocales(active.locales, locales) && active.timezone === timezone) {\n return;\n }\n\n active = { locales, timezone };\n notify();\n}\n\nexport function configTimezone(): string | null {\n return active.timezone;\n}\n\nexport function subscribeConfig(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nexport function useConfig(): Config {\n return useSyncExternalStore(subscribe, snapshot, () => fallback);\n}\n"],"mappings":";;AAQA,IAAM,WAAmB;CAAE,SAAS,CAAC;CAAG,UAAU;AAAK;AACvD,IAAM,4BAAY,IAAI,IAAgB;AAEtC,IAAI,SAAiB;AAErB,SAAS,iBAAiB,SAAkD;CAC1E,OAAO,MAAM,KAAK,IAAI,KAAK,WAAW,CAAC,EAAA,CAAG,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC;AAC3F;AAEA,SAAS,YAAY,MAAyB,OAAmC;CAC/E,OAAO,KAAK,WAAW,MAAM,UAAU,KAAK,OAAO,QAAQ,UAAU,WAAW,MAAM,MAAM;AAC9F;AAEA,SAAS,WAAmB;CAC1B,OAAO;AACT;AAEA,SAAS,UAAU,UAAkC;CACnD,UAAU,IAAI,QAAQ;CAEtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,SAAS,SAAe;CACtB,UAAU,SAAS,aAAa,SAAS,CAAC;AAC5C;AAEA,SAAgB,UAAU,QAAsC;CAC9D,MAAM,UAAU,iBAAiB,QAAQ,OAAO;CAChD,MAAM,WAAW,QAAQ,YAAY;CAErC,IAAI,YAAY,OAAO,SAAS,OAAO,KAAK,OAAO,aAAa,UAC9D;CAGF,SAAS;EAAE;EAAS;CAAS;CAC7B,OAAO;AACT;AAEA,SAAgB,iBAAgC;CAC9C,OAAO,OAAO;AAChB;AAEA,SAAgB,gBAAgB,UAAkC;CAChE,UAAU,IAAI,QAAQ;CAEtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,SAAgB,YAAoB;CAClC,OAAO,qBAAqB,WAAW,gBAAgB,QAAQ;AACjE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { i18n as I18nInstance } from 'i18next';
|
|
2
|
+
/**
|
|
3
|
+
* i18next's built-in `datetime` formatter throws on a string, and
|
|
4
|
+
* `Translatable::with()` sends dates over the wire as ISO 8601 strings, so
|
|
5
|
+
* coercion to `Date` is required first.
|
|
6
|
+
*
|
|
7
|
+
* Replaces i18next's built-in `datetime` formatter on the shared instance,
|
|
8
|
+
* for every consumer of it — not just Lattice's own translations.
|
|
9
|
+
*
|
|
10
|
+
* Pins the formatter to Lattice's own {@link currentTimezone}, the same
|
|
11
|
+
* source `<DateTime>` renders through, so both agree on calendar day.
|
|
12
|
+
*/
|
|
13
|
+
export declare function registerDateTimeFormatter(instance: I18nInstance): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { toDate } from "../format/date-time.js";
|
|
2
|
+
import { currentTimezone } from "./timezone.js";
|
|
3
|
+
//#region resources/js/i18n/date-time-formatter.ts
|
|
4
|
+
/**
|
|
5
|
+
* i18next's built-in `datetime` formatter throws on a string, and
|
|
6
|
+
* `Translatable::with()` sends dates over the wire as ISO 8601 strings, so
|
|
7
|
+
* coercion to `Date` is required first.
|
|
8
|
+
*
|
|
9
|
+
* Replaces i18next's built-in `datetime` formatter on the shared instance,
|
|
10
|
+
* for every consumer of it — not just Lattice's own translations.
|
|
11
|
+
*
|
|
12
|
+
* Pins the formatter to Lattice's own {@link currentTimezone}, the same
|
|
13
|
+
* source `<DateTime>` renders through, so both agree on calendar day.
|
|
14
|
+
*/
|
|
15
|
+
function registerDateTimeFormatter(instance) {
|
|
16
|
+
instance.services.formatter?.add("datetime", (value, lng, options) => {
|
|
17
|
+
const date = toDate(value);
|
|
18
|
+
if (!date) return String(value ?? "");
|
|
19
|
+
return new Intl.DateTimeFormat(lng, {
|
|
20
|
+
timeZone: currentTimezone(),
|
|
21
|
+
...options
|
|
22
|
+
}).format(date);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { registerDateTimeFormatter };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=date-time-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-time-formatter.js","names":[],"sources":["../../resources/js/i18n/date-time-formatter.ts"],"sourcesContent":["import type { i18n as I18nInstance } from \"i18next\";\nimport { toDate } from \"@lattice-php/lattice/format/date-time\";\nimport { currentTimezone } from \"./timezone\";\n\n/**\n * i18next's built-in `datetime` formatter throws on a string, and\n * `Translatable::with()` sends dates over the wire as ISO 8601 strings, so\n * coercion to `Date` is required first.\n *\n * Replaces i18next's built-in `datetime` formatter on the shared instance,\n * for every consumer of it — not just Lattice's own translations.\n *\n * Pins the formatter to Lattice's own {@link currentTimezone}, the same\n * source `<DateTime>` renders through, so both agree on calendar day.\n */\nexport function registerDateTimeFormatter(instance: I18nInstance): void {\n instance.services.formatter?.add(\"datetime\", (value, lng, options) => {\n const date = toDate(value);\n\n if (!date) {\n return String(value ?? \"\");\n }\n\n return new Intl.DateTimeFormat(lng, { timeZone: currentTimezone(), ...options }).format(date);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,SAAgB,0BAA0B,UAA8B;CACtE,SAAS,SAAS,WAAW,IAAI,aAAa,OAAO,KAAK,YAAY;EACpE,MAAM,OAAO,OAAO,KAAK;EAEzB,IAAI,CAAC,MACH,OAAO,OAAO,SAAS,EAAE;EAG3B,OAAO,IAAI,KAAK,eAAe,KAAK;GAAE,UAAU,gBAAgB;GAAG,GAAG;EAAQ,CAAC,CAAC,CAAC,OAAO,IAAI;CAC9F,CAAC;AACH"}
|
package/dist/i18n/date-time.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useLocale } from "./locale.js";
|
|
2
|
-
import { useTimezone } from "./timezone.js";
|
|
3
2
|
import { formatDateValue, preciseDateTime } from "../format/date-time.js";
|
|
3
|
+
import { useTimezone } from "./timezone.js";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
//#region resources/js/i18n/date-time.tsx
|
|
6
6
|
function DateTime({ value, dateStyle = "medium", timeStyle = "short" }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-time.js","names":[],"sources":["../../resources/js/i18n/date-time.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport {\n type FormatOptions,\n formatDateValue,\n preciseDateTime,\n} from \"@lattice-php/lattice/format/date-time\";\nimport type { DateTimeStyle } from \"@lattice-php/lattice/types/generated\";\nimport { useLocale } from \"./locale\";\nimport { useTimezone } from \"./timezone\";\n\nexport type DateTimeProps = {\n value: unknown;\n dateStyle?: DateTimeStyle | null;\n timeStyle?: DateTimeStyle | null;\n};\n\nexport function DateTime({\n value,\n dateStyle = \"medium\",\n timeStyle = \"short\",\n}: DateTimeProps): ReactNode {\n const { locale } = useLocale();\n const { timezone } = useTimezone();\n\n if (value === null || value === undefined || value === \"\") {\n return null;\n }\n\n const options: FormatOptions = { locale, timeZone: timezone };\n const text = formatDateValue(value, { dateStyle, timeStyle }, options);\n const iso = isoOrNull(value);\n const title = preciseDateTime(value, options);\n\n return (\n <time dateTime={iso ?? undefined} title={title || undefined}>\n {text}\n </time>\n );\n}\n\nfunction isoOrNull(value: unknown): string | null {\n const date = new Date(String(value));\n\n return Number.isNaN(date.getTime()) ? null : date.toISOString();\n}\n"],"mappings":";;;;;AAgBA,SAAgB,SAAS,EACvB,OACA,YAAY,UACZ,YAAY,WACe;CAC3B,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,EAAE,aAAa,YAAY;CAEjC,IAAI,UAAU,QAAQ,UAAU,KAAA,KAAa,UAAU,IACrD,OAAO;CAGT,MAAM,UAAyB;EAAE;EAAQ,UAAU;CAAS;CAC5D,MAAM,OAAO,gBAAgB,OAAO;EAAE;EAAW;CAAU,GAAG,OAAO;CACrE,MAAM,MAAM,UAAU,KAAK;CAC3B,MAAM,QAAQ,gBAAgB,OAAO,OAAO;CAE5C,OACE,oBAAC,QAAD;EAAM,UAAU,OAAO,KAAA;EAAW,OAAO,SAAS,KAAA;
|
|
1
|
+
{"version":3,"file":"date-time.js","names":[],"sources":["../../resources/js/i18n/date-time.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport {\n type FormatOptions,\n formatDateValue,\n preciseDateTime,\n} from \"@lattice-php/lattice/format/date-time\";\nimport type { DateTimeStyle } from \"@lattice-php/lattice/types/generated\";\nimport { useLocale } from \"./locale\";\nimport { useTimezone } from \"./timezone\";\n\nexport type DateTimeProps = {\n value: unknown;\n dateStyle?: DateTimeStyle | null;\n timeStyle?: DateTimeStyle | null;\n};\n\nexport function DateTime({\n value,\n dateStyle = \"medium\",\n timeStyle = \"short\",\n}: DateTimeProps): ReactNode {\n const { locale } = useLocale();\n const { timezone } = useTimezone();\n\n if (value === null || value === undefined || value === \"\") {\n return null;\n }\n\n const options: FormatOptions = { locale, timeZone: timezone };\n const text = formatDateValue(value, { dateStyle, timeStyle }, options);\n const iso = isoOrNull(value);\n const title = preciseDateTime(value, options);\n\n return (\n <time dateTime={iso ?? undefined} title={title || undefined}>\n {text}\n </time>\n );\n}\n\nfunction isoOrNull(value: unknown): string | null {\n const date = new Date(String(value));\n\n return Number.isNaN(date.getTime()) ? null : date.toISOString();\n}\n"],"mappings":";;;;;AAgBA,SAAgB,SAAS,EACvB,OACA,YAAY,UACZ,YAAY,WACe;CAC3B,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,EAAE,aAAa,YAAY;CAEjC,IAAI,UAAU,QAAQ,UAAU,KAAA,KAAa,UAAU,IACrD,OAAO;CAGT,MAAM,UAAyB;EAAE;EAAQ,UAAU;CAAS;CAC5D,MAAM,OAAO,gBAAgB,OAAO;EAAE;EAAW;CAAU,GAAG,OAAO;CACrE,MAAM,MAAM,UAAU,KAAK;CAC3B,MAAM,QAAQ,gBAAgB,OAAO,OAAO;CAE5C,OACE,oBAAC,QAAD;EAAM,UAAU,OAAO,KAAA;EAAW,OAAO,SAAS,KAAA;EAC/C,UAAA;CACG,CAAA;AAEV;AAEA,SAAS,UAAU,OAA+B;CAChD,MAAM,OAAO,IAAI,KAAK,OAAO,KAAK,CAAC;CAEnC,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,IAAI,OAAO,KAAK,YAAY;AAChE"}
|
package/dist/i18n/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { currentLocale, localeHeader, setLocale, useLocale } from "./locale.js";
|
|
2
|
+
import { currentTimezone, setTimezone, useTimezone } from "./timezone.js";
|
|
2
3
|
import { i18n, translate, useT } from "./instance.js";
|
|
3
4
|
import { LocaleReload } from "./locale-reload.js";
|
|
4
5
|
import { i18nConfigFromPageProps } from "./shared-props.js";
|
|
5
6
|
import { configureI18n, enableBackend } from "./backend.js";
|
|
6
7
|
import { LocaleSwitcher, useLocaleOptions } from "./locale-switcher.js";
|
|
7
8
|
import { configureI18nFromPageProps } from "./page-props.js";
|
|
8
|
-
import { currentTimezone, setTimezone, useTimezone } from "./timezone.js";
|
|
9
9
|
import { DateTime } from "./date-time.js";
|
|
10
10
|
export { DateTime, LocaleReload, LocaleSwitcher, configureI18n, configureI18nFromPageProps, currentLocale, currentTimezone, enableBackend, i18n, i18nConfigFromPageProps, localeHeader, setLocale, setTimezone, translate, useLocale, useLocaleOptions, useT, useTimezone };
|
package/dist/i18n/instance.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { currentLocale, subscribeLocale, useLocale } from "./locale.js";
|
|
2
2
|
import { useConfig } from "./config.js";
|
|
3
|
+
import { registerDateTimeFormatter } from "./date-time-formatter.js";
|
|
3
4
|
import { useCallback, useSyncExternalStore } from "react";
|
|
4
5
|
import i18next from "i18next";
|
|
5
6
|
//#region resources/js/i18n/instance.ts
|
|
@@ -43,6 +44,7 @@ function ensureI18n(extend) {
|
|
|
43
44
|
interpolation: { escapeValue: false }
|
|
44
45
|
};
|
|
45
46
|
initialization = i18n.init(extend ? extend(base) : base);
|
|
47
|
+
registerDateTimeFormatter(i18n);
|
|
46
48
|
}
|
|
47
49
|
return initialization;
|
|
48
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance.js","names":[],"sources":["../../resources/js/i18n/instance.ts"],"sourcesContent":["import i18next, { type i18n as I18nInstance, type InitOptions } from \"i18next\";\nimport { useCallback, useSyncExternalStore } from \"react\";\nimport { useConfig } from \"./config\";\nimport { currentLocale, subscribeLocale, useLocale } from \"./locale\";\n\nexport const DEFAULT_NAMESPACE = \"lattice\";\n\ntype TranslationFunction = (\n key: string,\n defaultValue?: string,\n options?: Record<string, unknown>,\n) => string;\n\ntype TranslationResult = {\n t: TranslationFunction;\n i18n: I18nInstance;\n locale: string;\n locales: readonly string[];\n ready: boolean;\n setLocale: (locale: string) => void;\n};\n\nexport const i18n: I18nInstance = i18next.createInstance();\n\nlet initialization: Promise<unknown> | undefined;\nlet revision = 0;\n\nfunction subscribe(onStoreChange: () => void): () => void {\n const listener = () => {\n revision += 1;\n onStoreChange();\n };\n\n i18n.on(\"initialized\", listener);\n i18n.on(\"loaded\", listener);\n i18n.on(\"languageChanged\", listener);\n i18n.store?.on(\"added\", listener);\n i18n.store?.on(\"removed\", listener);\n\n return () => {\n i18n.off(\"initialized\", listener);\n i18n.off(\"loaded\", listener);\n i18n.off(\"languageChanged\", listener);\n i18n.store?.off(\"added\", listener);\n i18n.store?.off(\"removed\", listener);\n };\n}\n\nfunction snapshot(): number {\n return revision;\n}\n\n/**\n * Initialize the instance exactly once. The first caller wins — a rendered\n * component (inline English, zero config) or `enableBackend()`, which registers\n * its backend first because i18next can only wire a backend during `init`.\n */\nexport function ensureI18n(extend?: (base: InitOptions) => InitOptions): Promise<unknown> {\n if (!initialization) {\n const base: InitOptions = {\n lng: currentLocale(),\n fallbackLng: \"en\",\n ns: [DEFAULT_NAMESPACE],\n defaultNS: DEFAULT_NAMESPACE,\n interpolation: { escapeValue: false },\n };\n\n initialization = i18n.init(extend ? extend(base) : base);\n }\n\n return initialization;\n}\n\nsubscribeLocale((locale) => {\n void ensureI18n().then(() => {\n if (i18n.language !== locale) {\n void i18n.changeLanguage(locale);\n }\n });\n});\n\n/**\n * Eagerly load the namespaces for the given locales so a later\n * `changeLanguage` resolves them from the store instead of an HTTP round-trip,\n * which would otherwise flash the fallback language on switch. The active\n * locale is already loaded by {@link ensureI18n}, so it is skipped.\n */\nexport async function preloadLanguages(locales: readonly string[]): Promise<void> {\n const pending = locales.filter((locale) => locale !== currentLocale());\n\n if (pending.length === 0) {\n return;\n }\n\n await ensureI18n();\n await i18n.loadLanguages([...pending]);\n}\n\nexport function useT(namespace: string): TranslationResult {\n ensureI18n();\n useSyncExternalStore(subscribe, snapshot, snapshot);\n const { locales } = useConfig();\n const { locale, setLocale } = useLocale();\n\n const t = useCallback<TranslationFunction>(\n (key, defaultValue = key, options = {}) => translate(namespace, key, defaultValue, options),\n [namespace],\n );\n\n return { t, i18n, locale, locales, ready: i18n.isInitialized, setLocale };\n}\n\nexport function translate(\n namespace: string,\n key: string,\n defaultValue: string,\n options?: Record<string, unknown>,\n): string {\n ensureI18n();\n\n if (!i18n.isInitialized || !i18n.hasLoadedNamespace(namespace)) {\n return i18n.t(key, defaultValue, { ns: namespace, ...options, saveMissing: false });\n }\n\n return i18n.t(key, defaultValue, { ns: namespace, ...options });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"instance.js","names":[],"sources":["../../resources/js/i18n/instance.ts"],"sourcesContent":["import i18next, { type i18n as I18nInstance, type InitOptions } from \"i18next\";\nimport { useCallback, useSyncExternalStore } from \"react\";\nimport { useConfig } from \"./config\";\nimport { registerDateTimeFormatter } from \"./date-time-formatter\";\nimport { currentLocale, subscribeLocale, useLocale } from \"./locale\";\n\nexport const DEFAULT_NAMESPACE = \"lattice\";\n\ntype TranslationFunction = (\n key: string,\n defaultValue?: string,\n options?: Record<string, unknown>,\n) => string;\n\ntype TranslationResult = {\n t: TranslationFunction;\n i18n: I18nInstance;\n locale: string;\n locales: readonly string[];\n ready: boolean;\n setLocale: (locale: string) => void;\n};\n\nexport const i18n: I18nInstance = i18next.createInstance();\n\nlet initialization: Promise<unknown> | undefined;\nlet revision = 0;\n\nfunction subscribe(onStoreChange: () => void): () => void {\n const listener = () => {\n revision += 1;\n onStoreChange();\n };\n\n i18n.on(\"initialized\", listener);\n i18n.on(\"loaded\", listener);\n i18n.on(\"languageChanged\", listener);\n i18n.store?.on(\"added\", listener);\n i18n.store?.on(\"removed\", listener);\n\n return () => {\n i18n.off(\"initialized\", listener);\n i18n.off(\"loaded\", listener);\n i18n.off(\"languageChanged\", listener);\n i18n.store?.off(\"added\", listener);\n i18n.store?.off(\"removed\", listener);\n };\n}\n\nfunction snapshot(): number {\n return revision;\n}\n\n/**\n * Initialize the instance exactly once. The first caller wins — a rendered\n * component (inline English, zero config) or `enableBackend()`, which registers\n * its backend first because i18next can only wire a backend during `init`.\n */\nexport function ensureI18n(extend?: (base: InitOptions) => InitOptions): Promise<unknown> {\n if (!initialization) {\n const base: InitOptions = {\n lng: currentLocale(),\n fallbackLng: \"en\",\n ns: [DEFAULT_NAMESPACE],\n defaultNS: DEFAULT_NAMESPACE,\n interpolation: { escapeValue: false },\n };\n\n initialization = i18n.init(extend ? extend(base) : base);\n // `services.formatter` only exists once `init()` has run, so this must follow it.\n registerDateTimeFormatter(i18n);\n }\n\n return initialization;\n}\n\nsubscribeLocale((locale) => {\n void ensureI18n().then(() => {\n if (i18n.language !== locale) {\n void i18n.changeLanguage(locale);\n }\n });\n});\n\n/**\n * Eagerly load the namespaces for the given locales so a later\n * `changeLanguage` resolves them from the store instead of an HTTP round-trip,\n * which would otherwise flash the fallback language on switch. The active\n * locale is already loaded by {@link ensureI18n}, so it is skipped.\n */\nexport async function preloadLanguages(locales: readonly string[]): Promise<void> {\n const pending = locales.filter((locale) => locale !== currentLocale());\n\n if (pending.length === 0) {\n return;\n }\n\n await ensureI18n();\n await i18n.loadLanguages([...pending]);\n}\n\nexport function useT(namespace: string): TranslationResult {\n ensureI18n();\n useSyncExternalStore(subscribe, snapshot, snapshot);\n const { locales } = useConfig();\n const { locale, setLocale } = useLocale();\n\n const t = useCallback<TranslationFunction>(\n (key, defaultValue = key, options = {}) => translate(namespace, key, defaultValue, options),\n [namespace],\n );\n\n return { t, i18n, locale, locales, ready: i18n.isInitialized, setLocale };\n}\n\nexport function translate(\n namespace: string,\n key: string,\n defaultValue: string,\n options?: Record<string, unknown>,\n): string {\n ensureI18n();\n\n if (!i18n.isInitialized || !i18n.hasLoadedNamespace(namespace)) {\n return i18n.t(key, defaultValue, { ns: namespace, ...options, saveMissing: false });\n }\n\n return i18n.t(key, defaultValue, { ns: namespace, ...options });\n}\n"],"mappings":";;;;;;AAMA,IAAa,oBAAoB;AAiBjC,IAAa,OAAqB,QAAQ,eAAe;AAEzD,IAAI;AACJ,IAAI,WAAW;AAEf,SAAS,UAAU,eAAuC;CACxD,MAAM,iBAAiB;EACrB,YAAY;EACZ,cAAc;CAChB;CAEA,KAAK,GAAG,eAAe,QAAQ;CAC/B,KAAK,GAAG,UAAU,QAAQ;CAC1B,KAAK,GAAG,mBAAmB,QAAQ;CACnC,KAAK,OAAO,GAAG,SAAS,QAAQ;CAChC,KAAK,OAAO,GAAG,WAAW,QAAQ;CAElC,aAAa;EACX,KAAK,IAAI,eAAe,QAAQ;EAChC,KAAK,IAAI,UAAU,QAAQ;EAC3B,KAAK,IAAI,mBAAmB,QAAQ;EACpC,KAAK,OAAO,IAAI,SAAS,QAAQ;EACjC,KAAK,OAAO,IAAI,WAAW,QAAQ;CACrC;AACF;AAEA,SAAS,WAAmB;CAC1B,OAAO;AACT;;;;;;AAOA,SAAgB,WAAW,QAA+D;CACxF,IAAI,CAAC,gBAAgB;EACnB,MAAM,OAAoB;GACxB,KAAK,cAAc;GACnB,aAAa;GACb,IAAI,CAAC,iBAAiB;GACtB,WAAW;GACX,eAAe,EAAE,aAAa,MAAM;EACtC;EAEA,iBAAiB,KAAK,KAAK,SAAS,OAAO,IAAI,IAAI,IAAI;EAEvD,0BAA0B,IAAI;CAChC;CAEA,OAAO;AACT;AAEA,iBAAiB,WAAW;CAC1B,WAAgB,CAAC,CAAC,WAAW;EAC3B,IAAI,KAAK,aAAa,QACpB,KAAU,eAAe,MAAM;CAEnC,CAAC;AACH,CAAC;;;;;;;AAQD,eAAsB,iBAAiB,SAA2C;CAChF,MAAM,UAAU,QAAQ,QAAQ,WAAW,WAAW,cAAc,CAAC;CAErE,IAAI,QAAQ,WAAW,GACrB;CAGF,MAAM,WAAW;CACjB,MAAM,KAAK,cAAc,CAAC,GAAG,OAAO,CAAC;AACvC;AAEA,SAAgB,KAAK,WAAsC;CACzD,WAAW;CACX,qBAAqB,WAAW,UAAU,QAAQ;CAClD,MAAM,EAAE,YAAY,UAAU;CAC9B,MAAM,EAAE,QAAQ,cAAc,UAAU;CAOxC,OAAO;EAAE,GALC,aACP,KAAK,eAAe,KAAK,UAAU,CAAC,MAAM,UAAU,WAAW,KAAK,cAAc,OAAO,GAC1F,CAAC,SAAS,CAGH;EAAG;EAAM;EAAQ;EAAS,OAAO,KAAK;EAAe;CAAU;AAC1E;AAEA,SAAgB,UACd,WACA,KACA,cACA,SACQ;CACR,WAAW;CAEX,IAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,mBAAmB,SAAS,GAC3D,OAAO,KAAK,EAAE,KAAK,cAAc;EAAE,IAAI;EAAW,GAAG;EAAS,aAAa;CAAM,CAAC;CAGpF,OAAO,KAAK,EAAE,KAAK,cAAc;EAAE,IAAI;EAAW,GAAG;CAAQ,CAAC;AAChE"}
|
package/dist/i18n/locale.js
CHANGED
|
@@ -3,7 +3,7 @@ import { useSyncExternalStore } from "react";
|
|
|
3
3
|
//#region resources/js/i18n/locale.ts
|
|
4
4
|
var key = "locale";
|
|
5
5
|
var fallback = "en";
|
|
6
|
-
var maxAge =
|
|
6
|
+
var maxAge = 31536e3;
|
|
7
7
|
var listeners = /* @__PURE__ */ new Set();
|
|
8
8
|
var active;
|
|
9
9
|
function normalize(value) {
|
package/dist/i18n/locale.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locale.js","names":[],"sources":["../../resources/js/i18n/locale.ts"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\n\nexport type UseLocaleReturn = {\n readonly locale: string;\n readonly setLocale: (locale: string) => void;\n};\n\nconst key = \"locale\";\nconst fallback = \"en\";\nconst maxAge = 365 * 24 * 60 * 60;\nconst listeners = new Set<() => void>();\n\nlet active: string | undefined;\n\nfunction normalize(value: string): string {\n const next = value.trim();\n\n return next === \"\" ? fallback : next;\n}\n\nfunction storedValue(): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction cookieValue(): string | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const item = document.cookie\n .split(\";\")\n .map((cookie) => cookie.trim())\n .find((cookie) => cookie.startsWith(`${key}=`));\n\n if (!item) {\n return null;\n }\n\n try {\n return decodeURIComponent(item.slice(key.length + 1));\n } catch {\n return null;\n }\n}\n\nfunction documentValue(): string | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n return document.documentElement.lang || null;\n}\n\nfunction detectedLocale(): string {\n return normalize(storedValue() ?? cookieValue() ?? documentValue() ?? fallback);\n}\n\nfunction persist(locale: string): void {\n if (typeof document !== \"undefined\") {\n document.cookie = `${key}=${encodeURIComponent(locale)};path=/;max-age=${maxAge};SameSite=Lax`;\n document.documentElement.lang = locale;\n }\n\n if (typeof window !== \"undefined\") {\n try {\n localStorage.setItem(key, locale);\n } catch {\n return;\n }\n }\n}\n\nfunction snapshot(): string {\n active ??= detectedLocale();\n\n return active;\n}\n\nfunction subscribe(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nfunction notify(): void {\n listeners.forEach((listener) => listener());\n}\n\nfunction dispatch(locale: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.localeChange, { detail: { locale } }));\n}\n\nexport function currentLocale(): string {\n return snapshot();\n}\n\nexport function localeHeader(): Record<string, string> {\n return { \"Accept-Language\": currentLocale() };\n}\n\nexport function subscribeLocale(callback: (locale: string) => void): () => void {\n return subscribe(() => callback(currentLocale()));\n}\n\nexport function setLocale(locale: string): void {\n const previous = currentLocale();\n const next = normalize(locale);\n\n active = next;\n persist(next);\n\n if (next === previous) {\n return;\n }\n\n notify();\n dispatch(next);\n}\n\nexport function useLocale(): UseLocaleReturn {\n const locale = useSyncExternalStore(subscribe, snapshot, () => fallback);\n\n return { locale, setLocale } as const;\n}\n"],"mappings":";;;AAQA,IAAM,MAAM;AACZ,IAAM,WAAW;AACjB,IAAM,SAAS
|
|
1
|
+
{"version":3,"file":"locale.js","names":[],"sources":["../../resources/js/i18n/locale.ts"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\n\nexport type UseLocaleReturn = {\n readonly locale: string;\n readonly setLocale: (locale: string) => void;\n};\n\nconst key = \"locale\";\nconst fallback = \"en\";\nconst maxAge = 365 * 24 * 60 * 60;\nconst listeners = new Set<() => void>();\n\nlet active: string | undefined;\n\nfunction normalize(value: string): string {\n const next = value.trim();\n\n return next === \"\" ? fallback : next;\n}\n\nfunction storedValue(): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction cookieValue(): string | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const item = document.cookie\n .split(\";\")\n .map((cookie) => cookie.trim())\n .find((cookie) => cookie.startsWith(`${key}=`));\n\n if (!item) {\n return null;\n }\n\n try {\n return decodeURIComponent(item.slice(key.length + 1));\n } catch {\n return null;\n }\n}\n\nfunction documentValue(): string | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n return document.documentElement.lang || null;\n}\n\nfunction detectedLocale(): string {\n return normalize(storedValue() ?? cookieValue() ?? documentValue() ?? fallback);\n}\n\nfunction persist(locale: string): void {\n if (typeof document !== \"undefined\") {\n document.cookie = `${key}=${encodeURIComponent(locale)};path=/;max-age=${maxAge};SameSite=Lax`;\n document.documentElement.lang = locale;\n }\n\n if (typeof window !== \"undefined\") {\n try {\n localStorage.setItem(key, locale);\n } catch {\n return;\n }\n }\n}\n\nfunction snapshot(): string {\n active ??= detectedLocale();\n\n return active;\n}\n\nfunction subscribe(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nfunction notify(): void {\n listeners.forEach((listener) => listener());\n}\n\nfunction dispatch(locale: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.localeChange, { detail: { locale } }));\n}\n\nexport function currentLocale(): string {\n return snapshot();\n}\n\nexport function localeHeader(): Record<string, string> {\n return { \"Accept-Language\": currentLocale() };\n}\n\nexport function subscribeLocale(callback: (locale: string) => void): () => void {\n return subscribe(() => callback(currentLocale()));\n}\n\nexport function setLocale(locale: string): void {\n const previous = currentLocale();\n const next = normalize(locale);\n\n active = next;\n persist(next);\n\n if (next === previous) {\n return;\n }\n\n notify();\n dispatch(next);\n}\n\nexport function useLocale(): UseLocaleReturn {\n const locale = useSyncExternalStore(subscribe, snapshot, () => fallback);\n\n return { locale, setLocale } as const;\n}\n"],"mappings":";;;AAQA,IAAM,MAAM;AACZ,IAAM,WAAW;AACjB,IAAM,SAAS;AACf,IAAM,4BAAY,IAAI,IAAgB;AAEtC,IAAI;AAEJ,SAAS,UAAU,OAAuB;CACxC,MAAM,OAAO,MAAM,KAAK;CAExB,OAAO,SAAS,KAAK,WAAW;AAClC;AAEA,SAAS,cAA6B;CACpC,IAAI,OAAO,WAAW,aACpB,OAAO;CAGT,IAAI;EACF,OAAO,aAAa,QAAQ,GAAG;CACjC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,cAA6B;CACpC,IAAI,OAAO,aAAa,aACtB,OAAO;CAGT,MAAM,OAAO,SAAS,OACnB,MAAM,GAAG,CAAC,CACV,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC,CAC9B,MAAM,WAAW,OAAO,WAAW,GAAG,IAAI,EAAE,CAAC;CAEhD,IAAI,CAAC,MACH,OAAO;CAGT,IAAI;EACF,OAAO,mBAAmB,KAAK,MAAM,CAAc,CAAC;CACtD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,gBAA+B;CACtC,IAAI,OAAO,aAAa,aACtB,OAAO;CAGT,OAAO,SAAS,gBAAgB,QAAQ;AAC1C;AAEA,SAAS,iBAAyB;CAChC,OAAO,UAAU,YAAY,KAAK,YAAY,KAAK,cAAc,KAAK,QAAQ;AAChF;AAEA,SAAS,QAAQ,QAAsB;CACrC,IAAI,OAAO,aAAa,aAAa;EACnC,SAAS,SAAS,GAAG,IAAI,GAAG,mBAAmB,MAAM,EAAE,kBAAkB,OAAO;EAChF,SAAS,gBAAgB,OAAO;CAClC;CAEA,IAAI,OAAO,WAAW,aACpB,IAAI;EACF,aAAa,QAAQ,KAAK,MAAM;CAClC,QAAQ;EACN;CACF;AAEJ;AAEA,SAAS,WAAmB;CAC1B,WAAW,eAAe;CAE1B,OAAO;AACT;AAEA,SAAS,UAAU,UAAkC;CACnD,UAAU,IAAI,QAAQ;CAEtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,SAAS,SAAe;CACtB,UAAU,SAAS,aAAa,SAAS,CAAC;AAC5C;AAEA,SAAS,SAAS,QAAsB;CACtC,IAAI,OAAO,WAAW,aACpB;CAGF,OAAO,cAAc,IAAI,YAAY,cAAc,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAC1F;AAEA,SAAgB,gBAAwB;CACtC,OAAO,SAAS;AAClB;AAEA,SAAgB,eAAuC;CACrD,OAAO,EAAE,mBAAmB,cAAc,EAAE;AAC9C;AAEA,SAAgB,gBAAgB,UAAgD;CAC9E,OAAO,gBAAgB,SAAS,cAAc,CAAC,CAAC;AAClD;AAEA,SAAgB,UAAU,QAAsB;CAC9C,MAAM,WAAW,cAAc;CAC/B,MAAM,OAAO,UAAU,MAAM;CAE7B,SAAS;CACT,QAAQ,IAAI;CAEZ,IAAI,SAAS,UACX;CAGF,OAAO;CACP,SAAS,IAAI;AACf;AAEA,SAAgB,YAA6B;CAG3C,OAAO;EAAE,QAFM,qBAAqB,WAAW,gBAAgB,QAEtD;EAAQ;CAAU;AAC7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timezone.js","names":[],"sources":["../../resources/js/i18n/timezone.ts"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { configTimezone, subscribeConfig } from \"./config\";\n\nexport type UseTimezoneReturn = {\n readonly timezone: string;\n readonly setTimezone: (timezone: string) => void;\n};\n\nconst fallback = \"UTC\";\nconst listeners = new Set<() => void>();\n\nlet override: string | undefined;\n\nfunction detectedTimezone(): string {\n if (typeof Intl === \"undefined\") {\n return fallback;\n }\n\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction snapshot(): string {\n return override ?? configTimezone() ?? detectedTimezone();\n}\n\nfunction subscribe(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nfunction notify(): void {\n listeners.forEach((listener) => listener());\n}\n\nsubscribeConfig(() => notify());\n\nfunction dispatch(timezone: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.timezoneChange, { detail: { timezone } }));\n}\n\nexport function currentTimezone(): string {\n return snapshot();\n}\n\nexport function setTimezone(timezone: string): void {\n const previous = currentTimezone();\n const next = timezone.trim();\n\n override = next === \"\" ? undefined : next;\n\n if (currentTimezone() === previous) {\n return;\n }\n\n notify();\n dispatch(currentTimezone());\n}\n\nexport function useTimezone(): UseTimezoneReturn {\n const timezone = useSyncExternalStore(subscribe, snapshot, () => fallback);\n\n return { timezone, setTimezone } as const;\n}\n"],"mappings":";;;;AASA,IAAM,WAAW;AACjB,IAAM,4BAAY,IAAI,IAAgB;AAEtC,IAAI;AAEJ,SAAS,mBAA2B;CAClC,IAAI,OAAO,SAAS,aAClB,OAAO;CAGT,IAAI;EACF,OAAO,KAAK,eAAe,
|
|
1
|
+
{"version":3,"file":"timezone.js","names":[],"sources":["../../resources/js/i18n/timezone.ts"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { configTimezone, subscribeConfig } from \"./config\";\n\nexport type UseTimezoneReturn = {\n readonly timezone: string;\n readonly setTimezone: (timezone: string) => void;\n};\n\nconst fallback = \"UTC\";\nconst listeners = new Set<() => void>();\n\nlet override: string | undefined;\n\nfunction detectedTimezone(): string {\n if (typeof Intl === \"undefined\") {\n return fallback;\n }\n\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction snapshot(): string {\n return override ?? configTimezone() ?? detectedTimezone();\n}\n\nfunction subscribe(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nfunction notify(): void {\n listeners.forEach((listener) => listener());\n}\n\nsubscribeConfig(() => notify());\n\nfunction dispatch(timezone: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.timezoneChange, { detail: { timezone } }));\n}\n\nexport function currentTimezone(): string {\n return snapshot();\n}\n\nexport function setTimezone(timezone: string): void {\n const previous = currentTimezone();\n const next = timezone.trim();\n\n override = next === \"\" ? undefined : next;\n\n if (currentTimezone() === previous) {\n return;\n }\n\n notify();\n dispatch(currentTimezone());\n}\n\nexport function useTimezone(): UseTimezoneReturn {\n const timezone = useSyncExternalStore(subscribe, snapshot, () => fallback);\n\n return { timezone, setTimezone } as const;\n}\n"],"mappings":";;;;AASA,IAAM,WAAW;AACjB,IAAM,4BAAY,IAAI,IAAgB;AAEtC,IAAI;AAEJ,SAAS,mBAA2B;CAClC,IAAI,OAAO,SAAS,aAClB,OAAO;CAGT,IAAI;EACF,OAAO,KAAK,eAAe,CAAC,CAAC,gBAAgB,CAAC,CAAC,YAAY;CAC7D,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,WAAmB;CAC1B,OAAO,YAAY,eAAe,KAAK,iBAAiB;AAC1D;AAEA,SAAS,UAAU,UAAkC;CACnD,UAAU,IAAI,QAAQ;CAEtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,SAAS,SAAe;CACtB,UAAU,SAAS,aAAa,SAAS,CAAC;AAC5C;AAEA,sBAAsB,OAAO,CAAC;AAE9B,SAAS,SAAS,UAAwB;CACxC,IAAI,OAAO,WAAW,aACpB;CAGF,OAAO,cAAc,IAAI,YAAY,cAAc,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;AAC9F;AAEA,SAAgB,kBAA0B;CACxC,OAAO,SAAS;AAClB;AAEA,SAAgB,YAAY,UAAwB;CAClD,MAAM,WAAW,gBAAgB;CACjC,MAAM,OAAO,SAAS,KAAK;CAE3B,WAAW,SAAS,KAAK,KAAA,IAAY;CAErC,IAAI,gBAAgB,MAAM,UACxB;CAGF,OAAO;CACP,SAAS,gBAAgB,CAAC;AAC5B;AAEA,SAAgB,cAAiC;CAG/C,OAAO;EAAE,UAFQ,qBAAqB,WAAW,gBAAgB,QAExD;EAAU;CAAY;AACjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translatable.js","names":[],"sources":["../../resources/js/i18n/translatable.ts"],"sourcesContent":["import type { Translatable } from \"@lattice-php/lattice/types/generated\";\n\nexport type Translate = (\n key: string,\n defaultValue?: string,\n options?: Record<string, unknown>,\n) => string;\n\nexport function isTranslatable(value: unknown): value is Translatable {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { key?: unknown }).key === \"string\"\n );\n}\n\nfunction readPath(payload: Record<string, unknown>, path: string): unknown {\n return path.split(\".\").reduce<unknown>((node, segment) => {\n if (typeof node === \"object\" && node !== null) {\n return (node as Record<string, unknown>)[segment];\n }\n\n return undefined;\n }, payload);\n}\n\nexport function resolveText(value: string | Translatable | null, t: Translate): string | null {\n return isTranslatable(value) ? resolveTranslatable(value, {}, t) : value;\n}\n\nexport function resolveTranslatable(\n value: Translatable,\n payload: Record<string, unknown>,\n t: Translate,\n): string {\n const fromPayload: Record<string, unknown> = {};\n\n for (const [name, path] of Object.entries(value.payload)) {\n const read = readPath(payload, path);\n fromPayload[name] = read === undefined ? \"\" : read;\n }\n\n return t(value.key, value.key, { ...value.replacements, ...fromPayload });\n}\n"],"mappings":";AAQA,SAAgB,eAAe,OAAuC;CACpE,OACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAA4B,QAAQ;AAEhD;AAEA,SAAS,SAAS,SAAkC,MAAuB;CACzE,OAAO,KAAK,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"translatable.js","names":[],"sources":["../../resources/js/i18n/translatable.ts"],"sourcesContent":["import type { Translatable } from \"@lattice-php/lattice/types/generated\";\n\nexport type Translate = (\n key: string,\n defaultValue?: string,\n options?: Record<string, unknown>,\n) => string;\n\nexport function isTranslatable(value: unknown): value is Translatable {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { key?: unknown }).key === \"string\"\n );\n}\n\nfunction readPath(payload: Record<string, unknown>, path: string): unknown {\n return path.split(\".\").reduce<unknown>((node, segment) => {\n if (typeof node === \"object\" && node !== null) {\n return (node as Record<string, unknown>)[segment];\n }\n\n return undefined;\n }, payload);\n}\n\nexport function resolveText(value: string | Translatable | null, t: Translate): string | null {\n return isTranslatable(value) ? resolveTranslatable(value, {}, t) : value;\n}\n\nexport function resolveTranslatable(\n value: Translatable,\n payload: Record<string, unknown>,\n t: Translate,\n): string {\n const fromPayload: Record<string, unknown> = {};\n\n for (const [name, path] of Object.entries(value.payload)) {\n const read = readPath(payload, path);\n fromPayload[name] = read === undefined ? \"\" : read;\n }\n\n return t(value.key, value.key, { ...value.replacements, ...fromPayload });\n}\n"],"mappings":";AAQA,SAAgB,eAAe,OAAuC;CACpE,OACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAA4B,QAAQ;AAEhD;AAEA,SAAS,SAAS,SAAkC,MAAuB;CACzE,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,QAAiB,MAAM,YAAY;EACxD,IAAI,OAAO,SAAS,YAAY,SAAS,MACvC,OAAQ,KAAiC;CAI7C,GAAG,OAAO;AACZ;AAEA,SAAgB,YAAY,OAAqC,GAA6B;CAC5F,OAAO,eAAe,KAAK,IAAI,oBAAoB,OAAO,CAAC,GAAG,CAAC,IAAI;AACrE;AAEA,SAAgB,oBACd,OACA,SACA,GACQ;CACR,MAAM,cAAuC,CAAC;CAE9C,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,MAAM,OAAO,GAAG;EACxD,MAAM,OAAO,SAAS,SAAS,IAAI;EACnC,YAAY,QAAQ,SAAS,KAAA,IAAY,KAAK;CAChD;CAEA,OAAO,EAAE,MAAM,KAAK,MAAM,KAAK;EAAE,GAAG,MAAM;EAAc,GAAG;CAAY,CAAC;AAC1E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-renderer.js","names":[],"sources":["../../resources/js/icons/icon-renderer.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Icon, useSprite } from \"./sprite\";\n\nexport type IconRendererProps = {\n className?: string;\n icon: string;\n};\n\nexport type IconRendererFunction = (props: IconRendererProps) => ReactNode;\n\ntype IconRendererProviderProps = {\n children: ReactNode;\n mode?: \"replace\" | \"stack\";\n renderer: IconRendererFunction;\n};\n\nconst IconRenderersContext = createContext<IconRendererFunction[]>([]);\nconst loggedMissingIcons = new Set<string>();\n\nexport function IconRendererProvider({\n children,\n mode = \"stack\",\n renderer,\n}: IconRendererProviderProps) {\n const parentRenderers = useContext(IconRenderersContext);\n const renderers = useMemo(\n () => (mode === \"replace\" ? [renderer] : [renderer, ...parentRenderers]),\n [mode, parentRenderers, renderer],\n );\n\n return (\n <IconRenderersContext.Provider value={renderers}>{children}</IconRenderersContext.Provider>\n );\n}\n\nexport function IconRenderer({ className, icon }: IconRendererProps) {\n const renderers = useContext(IconRenderersContext);\n const { ids } = useSprite();\n\n for (const renderer of renderers) {\n const rendered = renderer({ className, icon });\n\n if (rendered !== null && rendered !== undefined && rendered !== false) {\n return rendered;\n }\n }\n\n // When the sprite is wired and the icon is genuinely absent, show a visible\n // marker. When `ids` is unknown (not yet wired), optimistically emit the\n // sprite reference rather than crying wolf.\n if (ids && !ids.includes(icon)) {\n logMissingIcon(icon);\n return <MissingIcon className={className} />;\n }\n\n return <Icon className={className} name={icon} />;\n}\n\nfunction MissingIcon({ className }: { className?: string }) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn(\"size-lt-icon-md text-lt-muted-fg\", className)}\n data-lattice-missing-icon=\"\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\nfunction logMissingIcon(icon: string): void {\n if (!import.meta.env.DEV || loggedMissingIcons.has(icon)) {\n return;\n }\n\n loggedMissingIcons.add(icon);\n console.log(`[Lattice] Missing icon renderer for \"${icon}\".`);\n}\n"],"mappings":";;;;;AAkBA,IAAM,uBAAuB,cAAsC,CAAC,CAAC;AAGrE,SAAgB,qBAAqB,EACnC,UACA,OAAO,SACP,YAC4B;CAC5B,MAAM,kBAAkB,WAAW,oBAAoB;CACvD,MAAM,YAAY,cACT,SAAS,YAAY,CAAC,QAAQ,IAAI,CAAC,UAAU,GAAG,eAAe,GACtE;EAAC;EAAM;EAAiB;CAAQ,CAClC;CAEA,OACE,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAY;CAAwC,CAAA;AAE9F;AAEA,SAAgB,aAAa,EAAE,WAAW,QAA2B;CACnE,MAAM,YAAY,WAAW,oBAAoB;CACjD,MAAM,EAAE,QAAQ,UAAU;CAE1B,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,WAAW,SAAS;GAAE;GAAW;EAAK,CAAC;EAE7C,IAAI,aAAa,QAAQ,aAAa,KAAA,KAAa,aAAa,OAC9D,OAAO;CAEX;CAKA,IAAI,OAAO,CAAC,IAAI,SAAS,IAAI,GAE3B,OAAO,oBAAC,aAAD,EAAwB,UAAY,CAAA;CAG7C,OAAO,oBAAC,MAAD;EAAiB;EAAW,MAAM;CAAO,CAAA;AAClD;AAEA,SAAS,YAAY,EAAE,aAAqC;CAC1D,OACE,qBAAC,OAAD;EACE,eAAY;EACZ,WAAW,GAAG,oCAAoC,SAAS;EAC3D,6BAA0B;EAC1B,MAAK;EACL,QAAO;EACP,eAAc;EACd,gBAAe;EACf,aAAY;EACZ,SAAQ;
|
|
1
|
+
{"version":3,"file":"icon-renderer.js","names":[],"sources":["../../resources/js/icons/icon-renderer.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Icon, useSprite } from \"./sprite\";\n\nexport type IconRendererProps = {\n className?: string;\n icon: string;\n};\n\nexport type IconRendererFunction = (props: IconRendererProps) => ReactNode;\n\ntype IconRendererProviderProps = {\n children: ReactNode;\n mode?: \"replace\" | \"stack\";\n renderer: IconRendererFunction;\n};\n\nconst IconRenderersContext = createContext<IconRendererFunction[]>([]);\nconst loggedMissingIcons = new Set<string>();\n\nexport function IconRendererProvider({\n children,\n mode = \"stack\",\n renderer,\n}: IconRendererProviderProps) {\n const parentRenderers = useContext(IconRenderersContext);\n const renderers = useMemo(\n () => (mode === \"replace\" ? [renderer] : [renderer, ...parentRenderers]),\n [mode, parentRenderers, renderer],\n );\n\n return (\n <IconRenderersContext.Provider value={renderers}>{children}</IconRenderersContext.Provider>\n );\n}\n\nexport function IconRenderer({ className, icon }: IconRendererProps) {\n const renderers = useContext(IconRenderersContext);\n const { ids } = useSprite();\n\n for (const renderer of renderers) {\n const rendered = renderer({ className, icon });\n\n if (rendered !== null && rendered !== undefined && rendered !== false) {\n return rendered;\n }\n }\n\n // When the sprite is wired and the icon is genuinely absent, show a visible\n // marker. When `ids` is unknown (not yet wired), optimistically emit the\n // sprite reference rather than crying wolf.\n if (ids && !ids.includes(icon)) {\n logMissingIcon(icon);\n return <MissingIcon className={className} />;\n }\n\n return <Icon className={className} name={icon} />;\n}\n\nfunction MissingIcon({ className }: { className?: string }) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn(\"size-lt-icon-md text-lt-muted-fg\", className)}\n data-lattice-missing-icon=\"\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\nfunction logMissingIcon(icon: string): void {\n if (!import.meta.env.DEV || loggedMissingIcons.has(icon)) {\n return;\n }\n\n loggedMissingIcons.add(icon);\n console.log(`[Lattice] Missing icon renderer for \"${icon}\".`);\n}\n"],"mappings":";;;;;AAkBA,IAAM,uBAAuB,cAAsC,CAAC,CAAC;AAGrE,SAAgB,qBAAqB,EACnC,UACA,OAAO,SACP,YAC4B;CAC5B,MAAM,kBAAkB,WAAW,oBAAoB;CACvD,MAAM,YAAY,cACT,SAAS,YAAY,CAAC,QAAQ,IAAI,CAAC,UAAU,GAAG,eAAe,GACtE;EAAC;EAAM;EAAiB;CAAQ,CAClC;CAEA,OACE,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAY;CAAwC,CAAA;AAE9F;AAEA,SAAgB,aAAa,EAAE,WAAW,QAA2B;CACnE,MAAM,YAAY,WAAW,oBAAoB;CACjD,MAAM,EAAE,QAAQ,UAAU;CAE1B,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,WAAW,SAAS;GAAE;GAAW;EAAK,CAAC;EAE7C,IAAI,aAAa,QAAQ,aAAa,KAAA,KAAa,aAAa,OAC9D,OAAO;CAEX;CAKA,IAAI,OAAO,CAAC,IAAI,SAAS,IAAI,GAE3B,OAAO,oBAAC,aAAD,EAAwB,UAAY,CAAA;CAG7C,OAAO,oBAAC,MAAD;EAAiB;EAAW,MAAM;CAAO,CAAA;AAClD;AAEA,SAAS,YAAY,EAAE,aAAqC;CAC1D,OACE,qBAAC,OAAD;EACE,eAAY;EACZ,WAAW,GAAG,oCAAoC,SAAS;EAC3D,6BAA0B;EAC1B,MAAK;EACL,QAAO;EACP,eAAc;EACd,gBAAe;EACf,aAAY;EACZ,SAAQ;EATV,UAAA;GAWE,oBAAC,UAAD;IAAQ,IAAG;IAAK,IAAG;IAAK,GAAE;GAAM,CAAA;GAChC,oBAAC,QAAD,EAAM,GAAE,uCAAwC,CAAA;GAChD,oBAAC,QAAD,EAAM,GAAE,aAAc,CAAA;EACnB;;AAET"}
|