@lattice-php/lattice 0.15.0 → 0.17.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 +1 -1
- package/dist/action/use-action.js +1 -1
- package/dist/chat/types.d.ts +2 -10
- package/dist/core/components/button.js +34 -18
- package/dist/core/components/button.js.map +1 -1
- package/dist/core/components/chart.js +49 -2
- package/dist/core/components/chart.js.map +1 -1
- package/dist/core/components/control.d.ts +1 -3
- package/dist/core/components/control.js.map +1 -1
- package/dist/core/components/link.js +25 -29
- package/dist/core/components/link.js.map +1 -1
- package/dist/core/types.d.ts +22 -42
- package/dist/core/use-click-behavior.d.ts +42 -0
- package/dist/core/use-click-behavior.js +46 -0
- package/dist/core/use-click-behavior.js.map +1 -0
- package/dist/create-app.d.ts +8 -2
- package/dist/create-app.js +4 -2
- package/dist/create-app.js.map +1 -1
- package/dist/effects/registry.d.ts +9 -20
- package/dist/effects/registry.js +4 -6
- package/dist/effects/registry.js.map +1 -1
- package/dist/events/event-bridge.d.ts +1 -1
- package/dist/events/event-bridge.js +1 -1
- package/dist/events/event-bridge.js.map +1 -1
- package/dist/form/components/base/input-otp.d.ts +2 -1
- package/dist/form/components/base/input-otp.js.map +1 -1
- package/dist/form/components/conditions.d.ts +1 -1
- package/dist/form/components/conditions.js.map +1 -1
- package/dist/form/components/field-props.d.ts +2 -1
- package/dist/form/components/field-props.js.map +1 -1
- package/dist/form/components/field-scope.d.ts +2 -1
- package/dist/form/components/field-scope.js.map +1 -1
- package/dist/form/components/fields/date-picker-control.js +11 -13
- package/dist/form/components/fields/date-picker-control.js.map +1 -1
- package/dist/form/components/fields/row-action-menu.d.ts +2 -1
- package/dist/form/components/fields/row-action-menu.js.map +1 -1
- package/dist/form/components/fields/row-item.d.ts +2 -1
- package/dist/form/components/fields/row-item.js.map +1 -1
- package/dist/form/components/fields/table-rows.d.ts +2 -1
- package/dist/form/components/fields/table-rows.js.map +1 -1
- package/dist/form/components/fields/time-input.js +54 -15
- package/dist/form/components/fields/time-input.js.map +1 -1
- package/dist/form/components/fields/time-picker-columns.d.ts +24 -0
- package/dist/form/components/fields/time-picker-columns.js +76 -0
- package/dist/form/components/fields/time-picker-columns.js.map +1 -0
- package/dist/form/components/fields/time-picker.d.ts +18 -0
- package/dist/form/components/fields/time-picker.js +132 -0
- package/dist/form/components/fields/time-picker.js.map +1 -0
- package/dist/form/components/fields/use-row-collection.d.ts +2 -1
- package/dist/form/components/fields/use-row-collection.js.map +1 -1
- package/dist/form/components/form-path.d.ts +0 -1
- package/dist/form/components/form-path.js +1 -1
- package/dist/form/components/form-path.js.map +1 -1
- package/dist/form/components/prefill-targets.d.ts +1 -1
- package/dist/form/components/prefill-targets.js.map +1 -1
- package/dist/form/components/types.d.ts +5 -1
- package/dist/form/components/use-field-commit.d.ts +2 -1
- package/dist/form/components/use-field-commit.js.map +1 -1
- package/dist/form/components/use-form-resolver.d.ts +2 -1
- package/dist/form/components/use-form-resolver.js.map +1 -1
- package/dist/format/date-time.d.ts +12 -0
- package/dist/format/date-time.js +30 -0
- package/dist/format/date-time.js.map +1 -0
- package/dist/format/number.d.ts +2 -0
- package/dist/format/number.js +23 -0
- package/dist/format/number.js.map +1 -0
- package/dist/{table/components/cells → format}/numeric.js +1 -1
- package/dist/format/numeric.js.map +1 -0
- package/dist/format/value.d.ts +6 -0
- package/dist/format/value.js +17 -0
- package/dist/format/value.js.map +1 -0
- package/dist/i18n/config.d.ts +2 -1
- package/dist/i18n/config.js.map +1 -1
- package/dist/i18n/date-time.js +1 -1
- package/dist/i18n/date-time.js.map +1 -1
- package/dist/i18n/instance.d.ts +1 -1
- package/dist/i18n/instance.js.map +1 -1
- package/dist/i18n/locale-reload.d.ts +2 -1
- package/dist/i18n/locale-reload.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/layout/components.js +1 -1
- package/dist/layout/menu-item.js +43 -49
- package/dist/layout/menu-item.js.map +1 -1
- package/dist/notifications/api.d.ts +6 -0
- package/dist/notifications/api.js +21 -0
- package/dist/notifications/api.js.map +1 -0
- package/dist/notifications/components/empty-state.d.ts +1 -0
- package/dist/notifications/components/empty-state.js +21 -0
- package/dist/notifications/components/empty-state.js.map +1 -0
- package/dist/notifications/components/notification-item.d.ts +6 -0
- package/dist/notifications/components/notification-item.js +65 -0
- package/dist/notifications/components/notification-item.js.map +1 -0
- package/dist/notifications/components/notification-list.d.ts +10 -0
- package/dist/notifications/components/notification-list.js +38 -0
- package/dist/notifications/components/notification-list.js.map +1 -0
- package/dist/notifications/components/notifications-echo.d.ts +5 -0
- package/dist/notifications/components/notifications-echo.js +22 -0
- package/dist/notifications/components/notifications-echo.js.map +1 -0
- package/dist/notifications/components/notifications.d.ts +3 -0
- package/dist/notifications/components/notifications.js +109 -0
- package/dist/notifications/components/notifications.js.map +1 -0
- package/dist/notifications/index.d.ts +1 -0
- package/dist/notifications/index.js +11 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/store.d.ts +25 -0
- package/dist/notifications/store.js +100 -0
- package/dist/notifications/store.js.map +1 -0
- package/dist/notifications/types.d.ts +10 -0
- package/dist/notifications/types.js +0 -0
- package/dist/realtime/build-effects.d.ts +2 -1
- package/dist/realtime/build-effects.js.map +1 -1
- package/dist/realtime/subscriptions.js.map +1 -1
- package/dist/registry/eager.js +2 -1
- package/dist/registry/eager.js.map +1 -1
- package/dist/registry/lazy.js +2 -1
- package/dist/registry/lazy.js.map +1 -1
- package/dist/table/bulk.d.ts +2 -1
- package/dist/table/bulk.js.map +1 -1
- package/dist/table/components/bulk-bar.js +2 -2
- package/dist/table/components/cells/money-cell.js +11 -12
- package/dist/table/components/cells/money-cell.js.map +1 -1
- package/dist/table/components/cells/number-cell.js +11 -11
- package/dist/table/components/cells/number-cell.js.map +1 -1
- package/dist/table/components/cells/text-cell.js +1 -1
- package/dist/table/components/filter-controls.d.ts +0 -4
- package/dist/table/components/filter-controls.js.map +1 -1
- package/dist/table/components/table-cell.js.map +1 -1
- package/dist/table/format.d.ts +1 -10
- package/dist/table/format.js +2 -24
- package/dist/table/format.js.map +1 -1
- package/dist/table/types.d.ts +7 -17
- package/dist/types/generated.d.ts +137 -290
- package/dist/types/index.d.ts +1 -1
- package/dist/vite-client.d.ts +8 -0
- package/dist/vite.d.ts +35 -1
- package/dist/vite.js +60 -2
- package/dist/vite.js.map +1 -1
- package/package.json +13 -2
- package/resources/icons/bell.svg +16 -0
- package/resources/icons/clock.svg +16 -0
- package/dist/table/components/cells/numeric.js.map +0 -1
- /package/dist/{table/components/cells → format}/numeric.d.ts +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getActionEffects } from "../effects/dispatch.js";
|
|
2
|
+
import { useEffectDispatcher } from "../effects/use-effect-dispatcher.js";
|
|
3
|
+
import { useAction } from "../action/use-action.js";
|
|
4
|
+
import { Fragment, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region resources/js/core/use-click-behavior.tsx
|
|
6
|
+
/**
|
|
7
|
+
* The shared click model for Link/Button/MenuItem: a clickable carries exactly
|
|
8
|
+
* one behavior — navigate to an href, run a server action, or dispatch client
|
|
9
|
+
* effects. This resolves it without touching the action machinery, so plain
|
|
10
|
+
* links/labels stay cheap; the `action` behavior renders through {@link ActionTrigger}.
|
|
11
|
+
*/
|
|
12
|
+
function useClickBehavior(props) {
|
|
13
|
+
const dispatch = useEffectDispatcher();
|
|
14
|
+
const action = props.action ?? null;
|
|
15
|
+
const effects = props.effects ?? [];
|
|
16
|
+
if (action) return {
|
|
17
|
+
kind: "action",
|
|
18
|
+
action
|
|
19
|
+
};
|
|
20
|
+
if (effects.length > 0) return {
|
|
21
|
+
kind: "effects",
|
|
22
|
+
onClick: () => dispatch(getActionEffects(effects))
|
|
23
|
+
};
|
|
24
|
+
if (props.href != null && props.href !== "") return {
|
|
25
|
+
kind: "navigate",
|
|
26
|
+
href: props.href,
|
|
27
|
+
method: props.method ?? "get"
|
|
28
|
+
};
|
|
29
|
+
return { kind: "none" };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Runs a server action's gate (confirm/form) and renders its overlays, handing
|
|
33
|
+
* the host a click handler + processing state to render its own element with.
|
|
34
|
+
* Only mounted for the `action` behavior, so a plain link never runs `useAction`.
|
|
35
|
+
*/
|
|
36
|
+
function ActionTrigger({ action, children }) {
|
|
37
|
+
const { processing, requestSubmit, overlays } = useAction(action);
|
|
38
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [children({
|
|
39
|
+
onClick: requestSubmit,
|
|
40
|
+
processing
|
|
41
|
+
}), overlays] });
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { ActionTrigger, useClickBehavior };
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=use-click-behavior.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-click-behavior.js","names":[],"sources":["../../resources/js/core/use-click-behavior.tsx"],"sourcesContent":["import type { Method } from \"@inertiajs/core\";\nimport type { ReactNode } from \"react\";\nimport { useAction } from \"@lattice-php/lattice/action/use-action\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport { getActionEffects } from \"@lattice-php/lattice/effects/dispatch\";\nimport { useEffectDispatcher } from \"@lattice-php/lattice/effects/use-effect-dispatcher\";\nimport type { Effect } from \"@lattice-php/lattice/types/generated\";\n\nexport type ClickBehavior =\n | { kind: \"navigate\"; href: string; method: Method }\n | { kind: \"action\"; action: Node<\"action\"> }\n | { kind: \"effects\"; onClick: () => void }\n | { kind: \"none\" };\n\n/**\n * The shared click model for Link/Button/MenuItem: a clickable carries exactly\n * one behavior — navigate to an href, run a server action, or dispatch client\n * effects. This resolves it without touching the action machinery, so plain\n * links/labels stay cheap; the `action` behavior renders through {@link ActionTrigger}.\n */\nexport function useClickBehavior(props: {\n href?: string | null;\n method?: Method | null;\n action?: Node | null;\n effects?: Effect[] | null;\n}): ClickBehavior {\n const dispatch = useEffectDispatcher();\n const action = (props.action ?? null) as Node<\"action\"> | null;\n const effects = props.effects ?? [];\n\n if (action) {\n return { kind: \"action\", action };\n }\n\n if (effects.length > 0) {\n return { kind: \"effects\", onClick: () => dispatch(getActionEffects(effects)) };\n }\n\n if (props.href != null && props.href !== \"\") {\n return { kind: \"navigate\", href: props.href, method: props.method ?? \"get\" };\n }\n\n return { kind: \"none\" };\n}\n\nexport type TriggerState = { onClick: () => void; processing: boolean };\n\n/**\n * Runs a server action's gate (confirm/form) and renders its overlays, handing\n * the host a click handler + processing state to render its own element with.\n * Only mounted for the `action` behavior, so a plain link never runs `useAction`.\n */\nexport function ActionTrigger({\n action,\n children,\n}: {\n action: Node<\"action\">;\n children: (trigger: TriggerState) => ReactNode;\n}) {\n const { processing, requestSubmit, overlays } = useAction(action);\n\n return (\n <>\n {children({ onClick: requestSubmit, processing })}\n {overlays}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;AAoBA,SAAgB,iBAAiB,OAKf;CAChB,MAAM,WAAW,oBAAoB;CACrC,MAAM,SAAU,MAAM,UAAU;CAChC,MAAM,UAAU,MAAM,WAAW,CAAC;CAElC,IAAI,QACF,OAAO;EAAE,MAAM;EAAU;CAAO;CAGlC,IAAI,QAAQ,SAAS,GACnB,OAAO;EAAE,MAAM;EAAW,eAAe,SAAS,iBAAiB,OAAO,CAAC;CAAE;CAG/E,IAAI,MAAM,QAAQ,QAAQ,MAAM,SAAS,IACvC,OAAO;EAAE,MAAM;EAAY,MAAM,MAAM;EAAM,QAAQ,MAAM,UAAU;CAAM;CAG7E,OAAO,EAAE,MAAM,OAAO;AACxB;;;;;;AASA,SAAgB,cAAc,EAC5B,QACA,YAIC;CACD,MAAM,EAAE,YAAY,eAAe,aAAa,UAAU,MAAM;CAEhE,OACE,qBAAA,UAAA,EAAA,UAAA,CACG,SAAS;EAAE,SAAS;EAAe;CAAW,CAAC,GAC/C,QACD,EAAA,CAAA;AAEN"}
|
package/dist/create-app.d.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { createInertiaApp } from '@inertiajs/react';
|
|
2
2
|
import { ReactElement } from 'react';
|
|
3
|
-
import { Registry } from './core/registry';
|
|
3
|
+
import { Plugin, Registry } from './core/registry';
|
|
4
4
|
import { SpriteValue } from './icons/sprite';
|
|
5
5
|
import { CreateLayoutResolverOptions, PageModules } from './inertia';
|
|
6
6
|
type InertiaAppOptions = NonNullable<Parameters<typeof createInertiaApp>[0]>;
|
|
7
7
|
export type CreateLatticeAppOptions = Omit<InertiaAppOptions, "resolve" | "layout" | "setup" | "withApp" | "pages"> & {
|
|
8
8
|
registry?: Registry;
|
|
9
|
+
/**
|
|
10
|
+
* Component-package plugins to merge onto the registry — pass the
|
|
11
|
+
* Composer-discovered `virtual:lattice/plugins` here to register vendor
|
|
12
|
+
* components with no manual `extendRegistry` call.
|
|
13
|
+
*/
|
|
14
|
+
plugins?: Plugin[];
|
|
9
15
|
sprite?: SpriteValue;
|
|
10
16
|
/** Normal Inertia page modules, e.g. `import.meta.glob('./pages/**\/*.tsx')`. */
|
|
11
17
|
pages?: PageModules;
|
|
@@ -17,5 +23,5 @@ export type CreateLatticeAppOptions = Omit<InertiaAppOptions, "resolve" | "layou
|
|
|
17
23
|
* registry, sprite, flash toasts via Lattice's own Toaster — and theme
|
|
18
24
|
* initialization. Forwards any other createInertiaApp option.
|
|
19
25
|
*/
|
|
20
|
-
export declare function createLatticeApp({ registry, sprite, pages, defaultLayout, strictMode, ...inertiaOptions }?: CreateLatticeAppOptions): Promise<void | ((page: import('@inertiajs/core').Page<import('@inertiajs/core').PageProps>, renderToString: (element: ReactElement) => string) => Promise<import('@inertiajs/core').InertiaAppSSRResponse>)>;
|
|
26
|
+
export declare function createLatticeApp({ registry, plugins, sprite, pages, defaultLayout, strictMode, ...inertiaOptions }?: CreateLatticeAppOptions): Promise<void | ((page: import('@inertiajs/core').Page<import('@inertiajs/core').PageProps>, renderToString: (element: ReactElement) => string) => Promise<import('@inertiajs/core').InertiaAppSSRResponse>)>;
|
|
21
27
|
export {};
|
package/dist/create-app.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { initializeTheme } from "./appearance/index.js";
|
|
2
|
+
import { extendRegistry } from "./core/registry.js";
|
|
2
3
|
import { setDefaultRegistry } from "./core/registry-context.js";
|
|
3
4
|
import { createLayoutResolver, createPageResolver } from "./inertia.js";
|
|
4
5
|
import { ProviderBase } from "./provider-base.js";
|
|
@@ -12,8 +13,9 @@ import { jsx } from "react/jsx-runtime";
|
|
|
12
13
|
* registry, sprite, flash toasts via Lattice's own Toaster — and theme
|
|
13
14
|
* initialization. Forwards any other createInertiaApp option.
|
|
14
15
|
*/
|
|
15
|
-
function createLatticeApp({ registry, sprite, pages = {}, defaultLayout, strictMode = true, ...inertiaOptions } = {}) {
|
|
16
|
-
const
|
|
16
|
+
function createLatticeApp({ registry, plugins, sprite, pages = {}, defaultLayout, strictMode = true, ...inertiaOptions } = {}) {
|
|
17
|
+
const baseRegistry = registry ?? lazyRegistry;
|
|
18
|
+
const activeRegistry = plugins && plugins.length > 0 ? extendRegistry(baseRegistry, ...plugins) : baseRegistry;
|
|
17
19
|
setDefaultRegistry(activeRegistry);
|
|
18
20
|
const app = createInertiaApp({
|
|
19
21
|
...inertiaOptions,
|
package/dist/create-app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-app.js","names":[],"sources":["../resources/js/create-app.tsx"],"sourcesContent":["import { createInertiaApp } from \"@inertiajs/react\";\nimport type { ReactElement } from \"react\";\nimport { initializeTheme } from \"./appearance\";\nimport type
|
|
1
|
+
{"version":3,"file":"create-app.js","names":[],"sources":["../resources/js/create-app.tsx"],"sourcesContent":["import { createInertiaApp } from \"@inertiajs/react\";\nimport type { ReactElement } from \"react\";\nimport { initializeTheme } from \"./appearance\";\nimport { extendRegistry, type Plugin, type Registry } from \"./core/registry\";\nimport { setDefaultRegistry } from \"./core/registry-context\";\nimport type { SpriteValue } from \"./icons/sprite\";\nimport {\n createLayoutResolver,\n createPageResolver,\n type CreateLayoutResolverOptions,\n type PageModules,\n} from \"./inertia\";\nimport { ProviderBase } from \"./provider-base\";\nimport { registry as defaultRegistry } from \"./registry\";\n\ntype InertiaAppOptions = NonNullable<Parameters<typeof createInertiaApp>[0]>;\n\nexport type CreateLatticeAppOptions = Omit<\n InertiaAppOptions,\n \"resolve\" | \"layout\" | \"setup\" | \"withApp\" | \"pages\"\n> & {\n registry?: Registry;\n /**\n * Component-package plugins to merge onto the registry — pass the\n * Composer-discovered `virtual:lattice/plugins` here to register vendor\n * components with no manual `extendRegistry` call.\n */\n plugins?: Plugin[];\n sprite?: SpriteValue;\n /** Normal Inertia page modules, e.g. `import.meta.glob('./pages/**\\/*.tsx')`. */\n pages?: PageModules;\n defaultLayout?: CreateLayoutResolverOptions[\"defaultLayout\"];\n};\n\n/**\n * Bootstrap an Inertia app with the Lattice shell: the page/layout resolvers\n * (server-driven Lattice pages and normal Inertia pages alike), the Provider —\n * registry, sprite, flash toasts via Lattice's own Toaster — and theme\n * initialization. Forwards any other createInertiaApp option.\n */\nexport function createLatticeApp({\n registry,\n plugins,\n sprite,\n pages = {},\n defaultLayout,\n strictMode = true,\n ...inertiaOptions\n}: CreateLatticeAppOptions = {}) {\n const baseRegistry = registry ?? defaultRegistry;\n const activeRegistry =\n plugins && plugins.length > 0 ? extendRegistry(baseRegistry, ...plugins) : baseRegistry;\n\n setDefaultRegistry(activeRegistry);\n\n const app = createInertiaApp({\n ...inertiaOptions,\n strictMode,\n resolve: createPageResolver(pages),\n layout: createLayoutResolver({ defaultLayout }),\n withApp: (node: ReactElement): ReactElement => (\n <ProviderBase registry={activeRegistry} sprite={sprite}>\n {node}\n </ProviderBase>\n ),\n });\n\n initializeTheme();\n\n return app;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAwCA,SAAgB,iBAAiB,EAC/B,UACA,SACA,QACA,QAAQ,CAAC,GACT,eACA,aAAa,MACb,GAAG,mBACwB,CAAC,GAAG;CAC/B,MAAM,eAAe,YAAY;CACjC,MAAM,iBACJ,WAAW,QAAQ,SAAS,IAAI,eAAe,cAAc,GAAG,OAAO,IAAI;CAE7E,mBAAmB,cAAc;CAEjC,MAAM,MAAM,iBAAiB;EAC3B,GAAG;EACH;EACA,SAAS,mBAAmB,KAAK;EACjC,QAAQ,qBAAqB,EAAE,cAAc,CAAC;EAC9C,UAAU,SACR,oBAAC,cAAD;GAAc,UAAU;GAAwB;aAC7C;EACW,CAAA;CAElB,CAAC;CAED,gBAAgB;CAEhB,OAAO;AACT"}
|
|
@@ -1,37 +1,26 @@
|
|
|
1
1
|
import { ResolveProps } from '../core/types';
|
|
2
|
-
import { Effect } from '../types/generated';
|
|
2
|
+
import { Effect, EffectPropsMap } from '../types/generated';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* generated `Effect` union.
|
|
4
|
+
* Consumer apps augment this via `declare module "@lattice-php/lattice"` to type
|
|
5
|
+
* their custom effects' payloads; built-ins resolve through `EffectPropsMap`. The
|
|
6
|
+
* effect counterpart of `ComponentProps`.
|
|
8
7
|
*/
|
|
9
8
|
export interface EffectProps {
|
|
10
9
|
}
|
|
11
|
-
type
|
|
12
|
-
[TEffect in Effect as TEffect["type"]]: Omit<TEffect, "type">;
|
|
13
|
-
};
|
|
14
|
-
type EffectPayloadOf<TType extends string> = ResolveProps<EffectProps, EffectPayloads, TType, Record<string, unknown>>;
|
|
15
|
-
/**
|
|
16
|
-
* Resolves an effect `type` to its full shape — `{ type, ...payload }` — the way
|
|
17
|
-
* `Node<T>` pairs a type with its props, so built-ins and consumer effects alike
|
|
18
|
-
* always carry `type`. An unknown type falls back to the loose `Effect` union.
|
|
19
|
-
*/
|
|
10
|
+
type EffectPayloadOf<TType extends string> = ResolveProps<EffectProps, EffectPropsMap, TType, Record<string, unknown>>;
|
|
20
11
|
export type EffectOf<TType extends string> = string extends TType ? Effect : {
|
|
21
12
|
type: TType;
|
|
22
13
|
} & EffectPayloadOf<TType>;
|
|
23
14
|
export type EffectHandler<TType extends string = string> = (effect: EffectOf<TType>) => void;
|
|
24
15
|
export type EffectHandlerRegistry = Record<string, EffectHandler>;
|
|
25
16
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* for a typed payload, register through this.
|
|
17
|
+
* Author a handler against `EffectHandler<"my.type">` for a typed payload, then
|
|
18
|
+
* register it through this — it erases the type parameter for the loose registry.
|
|
29
19
|
*/
|
|
30
20
|
export declare function effectHandler<TType extends string>(_type: TType, fn: EffectHandler<TType>): EffectHandler;
|
|
31
21
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* — preserving today's behavior exactly.
|
|
22
|
+
* Imperative effects act directly; the rest bridge to the `lattice:*` DOM events
|
|
23
|
+
* that toast/callout/modal/fragment/form subscribe to.
|
|
35
24
|
*/
|
|
36
25
|
export declare const builtinEffectHandlers: EffectHandlerRegistry;
|
|
37
26
|
export declare function mergeEffectHandlers(...registries: Array<EffectHandlerRegistry | undefined>): EffectHandlerRegistry;
|
package/dist/effects/registry.js
CHANGED
|
@@ -3,9 +3,8 @@ import { setLocale } from "../i18n/locale.js";
|
|
|
3
3
|
import { router } from "@inertiajs/react";
|
|
4
4
|
//#region resources/js/effects/registry.ts
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* for a typed payload, register through this.
|
|
6
|
+
* Author a handler against `EffectHandler<"my.type">` for a typed payload, then
|
|
7
|
+
* register it through this — it erases the type parameter for the loose registry.
|
|
9
8
|
*/
|
|
10
9
|
function effectHandler(_type, fn) {
|
|
11
10
|
return fn;
|
|
@@ -22,9 +21,8 @@ function bridge(event) {
|
|
|
22
21
|
return (effect) => window.dispatchEvent(new CustomEvent(event, { detail: effect }));
|
|
23
22
|
}
|
|
24
23
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* — preserving today's behavior exactly.
|
|
24
|
+
* Imperative effects act directly; the rest bridge to the `lattice:*` DOM events
|
|
25
|
+
* that toast/callout/modal/fragment/form subscribe to.
|
|
28
26
|
*/
|
|
29
27
|
var builtinEffectHandlers = {
|
|
30
28
|
reloadPage: () => router.reload(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","names":[],"sources":["../../resources/js/effects/registry.ts"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport type { ResolveProps } from \"@lattice-php/lattice/core/types\";\nimport type { Effect } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/events/event-names\";\nimport { setLocale } from \"@lattice-php/lattice/i18n/locale\";\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"registry.js","names":[],"sources":["../../resources/js/effects/registry.ts"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport type { ResolveProps } from \"@lattice-php/lattice/core/types\";\nimport type { Effect, EffectPropsMap } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/events/event-names\";\nimport { setLocale } from \"@lattice-php/lattice/i18n/locale\";\n\n/**\n * Consumer apps augment this via `declare module \"@lattice-php/lattice\"` to type\n * their custom effects' payloads; built-ins resolve through `EffectPropsMap`. The\n * effect counterpart of `ComponentProps`.\n */\nexport interface EffectProps {}\n\ntype EffectPayloadOf<TType extends string> = ResolveProps<\n EffectProps,\n EffectPropsMap,\n TType,\n Record<string, unknown>\n>;\n\nexport type EffectOf<TType extends string> = string extends TType\n ? Effect\n : { type: TType } & EffectPayloadOf<TType>;\n\nexport type EffectHandler<TType extends string = string> = (effect: EffectOf<TType>) => void;\n\nexport type EffectHandlerRegistry = Record<string, EffectHandler>;\n\n/**\n * Author a handler against `EffectHandler<\"my.type\">` for a typed payload, then\n * register it through this — it erases the type parameter for the loose registry.\n */\nexport function effectHandler<TType extends string>(\n _type: TType,\n fn: EffectHandler<TType>,\n): EffectHandler {\n return fn as unknown as EffectHandler;\n}\n\nfunction triggerDownload(url: string): void {\n const link = document.createElement(\"a\");\n link.href = url;\n link.rel = \"noopener\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n}\n\nfunction bridge(event: string): EffectHandler {\n return (effect) => window.dispatchEvent(new CustomEvent(event, { detail: effect }));\n}\n\n/**\n * Imperative effects act directly; the rest bridge to the `lattice:*` DOM events\n * that toast/callout/modal/fragment/form subscribe to.\n */\nexport const builtinEffectHandlers: EffectHandlerRegistry = {\n reloadPage: () => router.reload(),\n redirect: effectHandler(\"redirect\", (effect) => router.visit(effect.url)),\n download: effectHandler(\"download\", (effect) => triggerDownload(effect.url)),\n localeChange: effectHandler(\"localeChange\", (effect) => setLocale(effect.locale)),\n toast: bridge(LATTICE_EVENT.toast),\n callout: bridge(LATTICE_EVENT.callout),\n reloadComponent: bridge(LATTICE_EVENT.reloadComponent),\n openModal: bridge(LATTICE_EVENT.openModal),\n closeModal: bridge(LATTICE_EVENT.closeModal),\n resetForm: bridge(LATTICE_EVENT.resetForm),\n toggleSidebar: bridge(LATTICE_EVENT.toggleSidebar),\n};\n\nexport function mergeEffectHandlers(\n ...registries: Array<EffectHandlerRegistry | undefined>\n): EffectHandlerRegistry {\n return registries.reduce<EffectHandlerRegistry>(\n (merged, registry) => ({ ...merged, ...registry }),\n {},\n );\n}\n"],"mappings":";;;;;;;;AAgCA,SAAgB,cACd,OACA,IACe;CACf,OAAO;AACT;AAEA,SAAS,gBAAgB,KAAmB;CAC1C,MAAM,OAAO,SAAS,cAAc,GAAG;CACvC,KAAK,OAAO;CACZ,KAAK,MAAM;CACX,SAAS,KAAK,YAAY,IAAI;CAC9B,KAAK,MAAM;CACX,KAAK,OAAO;AACd;AAEA,SAAS,OAAO,OAA8B;CAC5C,QAAQ,WAAW,OAAO,cAAc,IAAI,YAAY,OAAO,EAAE,QAAQ,OAAO,CAAC,CAAC;AACpF;;;;;AAMA,IAAa,wBAA+C;CAC1D,kBAAkB,OAAO,OAAO;CAChC,UAAU,cAAc,aAAa,WAAW,OAAO,MAAM,OAAO,GAAG,CAAC;CACxE,UAAU,cAAc,aAAa,WAAW,gBAAgB,OAAO,GAAG,CAAC;CAC3E,cAAc,cAAc,iBAAiB,WAAW,UAAU,OAAO,MAAM,CAAC;CAChF,OAAO,OAAO,cAAc,KAAK;CACjC,SAAS,OAAO,cAAc,OAAO;CACrC,iBAAiB,OAAO,cAAc,eAAe;CACrD,WAAW,OAAO,cAAc,SAAS;CACzC,YAAY,OAAO,cAAc,UAAU;CAC3C,WAAW,OAAO,cAAc,SAAS;CACzC,eAAe,OAAO,cAAc,aAAa;AACnD;AAEA,SAAgB,oBACd,GAAG,YACoB;CACvB,OAAO,WAAW,QACf,QAAQ,cAAc;EAAE,GAAG;EAAQ,GAAG;CAAS,IAChD,CAAC,CACH;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ToastMessage } from '../toast/toast';
|
|
2
|
-
|
|
2
|
+
declare const appearances: readonly ["light", "dark", "system"];
|
|
3
3
|
export type Appearance = (typeof appearances)[number];
|
|
4
4
|
type EventBridgeProps = {
|
|
5
5
|
onAppearanceChange?: (appearance: Appearance) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-bridge.js","names":[],"sources":["../../resources/js/events/event-bridge.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { onToast as subscribeToToasts } from \"@lattice-php/lattice/toast/toast\";\nimport type { ToastMessage } from \"@lattice-php/lattice/toast/toast\";\nimport { LATTICE_EVENT } from \"./event-names\";\n\
|
|
1
|
+
{"version":3,"file":"event-bridge.js","names":[],"sources":["../../resources/js/events/event-bridge.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { onToast as subscribeToToasts } from \"@lattice-php/lattice/toast/toast\";\nimport type { ToastMessage } from \"@lattice-php/lattice/toast/toast\";\nimport { LATTICE_EVENT } from \"./event-names\";\n\nconst appearances = [\"light\", \"dark\", \"system\"] as const;\n\nexport type Appearance = (typeof appearances)[number];\n\ntype EventBridgeProps = {\n onAppearanceChange?: (appearance: Appearance) => void;\n onLocaleChange?: (locale: string) => void;\n onToast?: (toast: ToastMessage) => void;\n};\n\ntype AppearanceEvent = CustomEvent<{\n value?: unknown;\n}>;\n\ntype LocaleEvent = CustomEvent<{\n locale?: unknown;\n}>;\n\nfunction isAppearance(value: unknown): value is Appearance {\n return appearances.some((appearance) => appearance === value);\n}\n\nexport function EventBridge({ onAppearanceChange, onLocaleChange, onToast }: EventBridgeProps) {\n useEffect(() => {\n if (!onToast) {\n return;\n }\n\n return subscribeToToasts(onToast);\n }, [onToast]);\n\n useEffect(() => {\n if (!onAppearanceChange) {\n return;\n }\n\n const listener = (event: Event): void => {\n const value = (event as AppearanceEvent).detail?.value;\n\n if (isAppearance(value)) {\n onAppearanceChange(value);\n }\n };\n\n window.addEventListener(LATTICE_EVENT.appearanceChange, listener);\n\n return () => {\n window.removeEventListener(LATTICE_EVENT.appearanceChange, listener);\n };\n }, [onAppearanceChange]);\n\n useEffect(() => {\n if (!onLocaleChange) {\n return;\n }\n\n const listener = (event: Event): void => {\n const locale = (event as LocaleEvent).detail?.locale;\n\n if (typeof locale === \"string\" && locale !== \"\") {\n onLocaleChange(locale);\n }\n };\n\n window.addEventListener(LATTICE_EVENT.localeChange, listener);\n\n return () => {\n window.removeEventListener(LATTICE_EVENT.localeChange, listener);\n };\n }, [onLocaleChange]);\n\n return null;\n}\n"],"mappings":";;;;AAKA,IAAM,cAAc;CAAC;CAAS;CAAQ;AAAQ;AAkB9C,SAAS,aAAa,OAAqC;CACzD,OAAO,YAAY,MAAM,eAAe,eAAe,KAAK;AAC9D;AAEA,SAAgB,YAAY,EAAE,oBAAoB,gBAAgB,SAAA,aAA6B;CAC7F,gBAAgB;EACd,IAAI,CAAC,WACH;EAGF,OAAO,QAAkB,SAAO;CAClC,GAAG,CAAC,SAAO,CAAC;CAEZ,gBAAgB;EACd,IAAI,CAAC,oBACH;EAGF,MAAM,YAAY,UAAuB;GACvC,MAAM,QAAS,MAA0B,QAAQ;GAEjD,IAAI,aAAa,KAAK,GACpB,mBAAmB,KAAK;EAE5B;EAEA,OAAO,iBAAiB,cAAc,kBAAkB,QAAQ;EAEhE,aAAa;GACX,OAAO,oBAAoB,cAAc,kBAAkB,QAAQ;EACrE;CACF,GAAG,CAAC,kBAAkB,CAAC;CAEvB,gBAAgB;EACd,IAAI,CAAC,gBACH;EAGF,MAAM,YAAY,UAAuB;GACvC,MAAM,SAAU,MAAsB,QAAQ;GAE9C,IAAI,OAAO,WAAW,YAAY,WAAW,IAC3C,eAAe,MAAM;EAEzB;EAEA,OAAO,iBAAiB,cAAc,cAAc,QAAQ;EAE5D,aAAa;GACX,OAAO,oBAAoB,cAAc,cAAc,QAAQ;EACjE;CACF,GAAG,CAAC,cAAc,CAAC;CAEnB,OAAO;AACT"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { OTPInput } from 'input-otp';
|
|
2
2
|
import { ComponentProps } from 'react';
|
|
3
|
-
|
|
3
|
+
type InputOTPProps = Omit<ComponentProps<typeof OTPInput>, "children" | "maxLength" | "render"> & {
|
|
4
4
|
length: number;
|
|
5
5
|
};
|
|
6
6
|
export declare function InputOTP({ length, containerClassName, pattern, ...props }: InputOTPProps): import("react").JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-otp.js","names":[],"sources":["../../../../resources/js/form/components/base/input-otp.tsx"],"sourcesContent":["import { OTPInput, REGEXP_ONLY_DIGITS, type SlotProps } from \"input-otp\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\n\nfunction Slot({ char, hasFakeCaret, isActive }: SlotProps) {\n return (\n <div\n className={cn(\n \"relative flex h-lt-control-md w-10 items-center justify-center border-y border-r border-lt-input text-base shadow-lt-xs transition-all first:rounded-l-lt-sm first:border-l last:rounded-r-lt-sm\",\n isActive && \"z-10 border-lt-ring ring-lt-ring/50 ring-[3px]\",\n )}\n >\n {char}\n {hasFakeCaret ? (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"bg-lt-fg h-5 w-px animate-pulse\" />\n </div>\n ) : null}\n </div>\n );\n}\n\
|
|
1
|
+
{"version":3,"file":"input-otp.js","names":[],"sources":["../../../../resources/js/form/components/base/input-otp.tsx"],"sourcesContent":["import { OTPInput, REGEXP_ONLY_DIGITS, type SlotProps } from \"input-otp\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\n\nfunction Slot({ char, hasFakeCaret, isActive }: SlotProps) {\n return (\n <div\n className={cn(\n \"relative flex h-lt-control-md w-10 items-center justify-center border-y border-r border-lt-input text-base shadow-lt-xs transition-all first:rounded-l-lt-sm first:border-l last:rounded-r-lt-sm\",\n isActive && \"z-10 border-lt-ring ring-lt-ring/50 ring-[3px]\",\n )}\n >\n {char}\n {hasFakeCaret ? (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"bg-lt-fg h-5 w-px animate-pulse\" />\n </div>\n ) : null}\n </div>\n );\n}\n\ntype InputOTPProps = Omit<ComponentProps<typeof OTPInput>, \"children\" | \"maxLength\" | \"render\"> & {\n length: number;\n};\n\nexport function InputOTP({\n length,\n containerClassName,\n pattern = REGEXP_ONLY_DIGITS,\n ...props\n}: InputOTPProps) {\n return (\n <OTPInput\n maxLength={length}\n pattern={pattern}\n containerClassName={cn(\n \"flex items-center gap-2 has-[:disabled]:opacity-50\",\n containerClassName,\n )}\n render={({ slots }) => (\n <div className=\"flex items-center\">\n {slots.map((slot, index) => (\n <Slot key={index} {...slot} />\n ))}\n </div>\n )}\n {...props}\n />\n );\n}\n"],"mappings":";;;;AAIA,SAAS,KAAK,EAAE,MAAM,cAAc,YAAuB;CACzD,OACE,qBAAC,OAAD;EACE,WAAW,GACT,oMACA,YAAY,gDACd;YAJF,CAMG,MACA,eACC,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,OAAD,EAAK,WAAU,kCAAmC,CAAA;EAC/C,CAAA,IACH,IACD;;AAET;AAMA,SAAgB,SAAS,EACvB,QACA,oBACA,UAAU,oBACV,GAAG,SACa;CAChB,OACE,oBAAC,UAAD;EACE,WAAW;EACF;EACT,oBAAoB,GAClB,sDACA,kBACF;EACA,SAAS,EAAE,YACT,oBAAC,OAAD;GAAK,WAAU;aACZ,MAAM,KAAK,MAAM,UAChB,oBAAC,MAAD,EAAkB,GAAI,KAAO,GAAlB,KAAkB,CAC9B;EACE,CAAA;EAEP,GAAI;CACL,CAAA;AAEL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conditions.js","names":[],"sources":["../../../resources/js/form/components/conditions.ts"],"sourcesContent":["import type { Condition, Op } from \"@lattice-php/lattice/types/generated\";\n\nexport type { Condition };\n\nexport type FieldConditions = {\n visible?: Condition[];\n required?: Condition[];\n readOnly?: Condition[];\n disabled?: Condition[];\n};\n\
|
|
1
|
+
{"version":3,"file":"conditions.js","names":[],"sources":["../../../resources/js/form/components/conditions.ts"],"sourcesContent":["import type { Condition, Op } from \"@lattice-php/lattice/types/generated\";\n\nexport type { Condition };\n\nexport type FieldConditions = {\n visible?: Condition[];\n required?: Condition[];\n readOnly?: Condition[];\n disabled?: Condition[];\n};\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\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: 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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"}
|
|
@@ -6,7 +6,7 @@ import { FieldConditions } from './conditions';
|
|
|
6
6
|
* lens the shared hooks read them through. Everything is optional because the
|
|
7
7
|
* lens is also applied to non-field nodes while walking the schema.
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
type FieldProps = {
|
|
10
10
|
conditions?: FieldConditions | null;
|
|
11
11
|
dependsOnAny?: boolean | null;
|
|
12
12
|
dependsOnKeys?: string[] | null;
|
|
@@ -25,3 +25,4 @@ export type FieldProps = {
|
|
|
25
25
|
};
|
|
26
26
|
export declare function fieldProps(node: Node): FieldProps;
|
|
27
27
|
export declare function walkFields(nodes: Node[] | undefined, visit: (props: FieldProps, node: Node) => void): void;
|
|
28
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-props.js","names":[],"sources":["../../../resources/js/form/components/field-props.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport type { FieldConditions } from \"./conditions\";\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.\n */\
|
|
1
|
+
{"version":3,"file":"field-props.js","names":[],"sources":["../../../resources/js/form/components/field-props.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport type { FieldConditions } from \"./conditions\";\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.\n */\ntype FieldProps = {\n conditions?: FieldConditions | null;\n dependsOnAny?: boolean | null;\n dependsOnKeys?: string[] | null;\n disabled?: boolean | null;\n helperText?: string | null;\n hidden?: boolean | null;\n label?: string | null;\n name?: string;\n editablePrefill?: boolean | null;\n prefillRefreshOn?: string[] | null;\n prefillResetOn?: string[] | null;\n readOnly?: boolean | null;\n required?: boolean | null;\n tooltip?: string | null;\n value?: unknown;\n};\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":";AA2BA,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,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
type FieldScopeValue = {
|
|
2
2
|
row: Record<string, unknown>;
|
|
3
3
|
rowId: string | null;
|
|
4
4
|
path: string;
|
|
@@ -19,3 +19,4 @@ export declare function FieldScopeProvider({ base, index, row, onChange, childre
|
|
|
19
19
|
}): import("react").JSX.Element;
|
|
20
20
|
/** Null outside a row so callers can preserve top-level behavior without a wrapper. */
|
|
21
21
|
export declare function useFieldScope(): FieldScopeValue | null;
|
|
22
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-scope.js","names":[],"sources":["../../../resources/js/form/components/field-scope.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport { appendPath, getPath, toHtmlName } from \"./form-path\";\nimport { buildOverrideKey, rowIdFrom } from \"./override-keys\";\n\
|
|
1
|
+
{"version":3,"file":"field-scope.js","names":[],"sources":["../../../resources/js/form/components/field-scope.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport { appendPath, getPath, toHtmlName } from \"./form-path\";\nimport { buildOverrideKey, rowIdFrom } from \"./override-keys\";\n\ntype FieldScopeValue = {\n row: Record<string, unknown>;\n rowId: string | null;\n path: string;\n values: Record<string, unknown>;\n identityPath: string;\n getValue: (name: string) => unknown;\n setValue: (name: string, value: unknown) => void;\n scopedName: (name: string) => string;\n errorKey: (name: string) => string;\n overrideKey: (name: string) => string;\n};\n\nconst FieldScopeContext = createContext<FieldScopeValue | null>(null);\n\nfunction childCollectionIdentity(base: string, parent: FieldScopeValue | null): string {\n if (!parent) {\n return base;\n }\n\n const local = base.startsWith(`${parent.path}.`) ? base.slice(parent.path.length + 1) : base;\n\n return appendPath(parent.identityPath, local);\n}\n\nexport function FieldScopeProvider({\n base,\n index,\n row,\n onChange,\n children,\n}: {\n base: string;\n index: number;\n row: Record<string, unknown>;\n onChange: (name: string, value: unknown) => void;\n children: React.ReactNode;\n}) {\n const parent = useContext(FieldScopeContext);\n\n const value = useMemo<FieldScopeValue>(() => {\n const scopedRow = row ?? {};\n const rowId = rowIdFrom(scopedRow);\n const path = appendPath(base, index);\n const identityCollection = childCollectionIdentity(base, parent);\n const identityPath = appendPath(identityCollection, rowId ?? index);\n\n return {\n row: scopedRow,\n rowId,\n path,\n values: parent ? { ...parent.values, ...scopedRow } : scopedRow,\n identityPath,\n getValue: (name) => getPath(scopedRow, name),\n setValue: onChange,\n scopedName: (name) => toHtmlName(appendPath(path, name)),\n errorKey: (name) => appendPath(path, name),\n overrideKey: (name) => buildOverrideKey(identityCollection, rowId, index, name),\n };\n }, [base, index, row, onChange, parent]);\n\n return <FieldScopeContext.Provider value={value}>{children}</FieldScopeContext.Provider>;\n}\n\n/** Null outside a row so callers can preserve top-level behavior without a wrapper. */\nexport function useFieldScope(): FieldScopeValue | null {\n return useContext(FieldScopeContext);\n}\n"],"mappings":";;;;;AAiBA,IAAM,oBAAoB,cAAsC,IAAI;AAEpE,SAAS,wBAAwB,MAAc,QAAwC;CACrF,IAAI,CAAC,QACH,OAAO;CAGT,MAAM,QAAQ,KAAK,WAAW,GAAG,OAAO,KAAK,EAAE,IAAI,KAAK,MAAM,OAAO,KAAK,SAAS,CAAC,IAAI;CAExF,OAAO,WAAW,OAAO,cAAc,KAAK;AAC9C;AAEA,SAAgB,mBAAmB,EACjC,MACA,OACA,KACA,UACA,YAOC;CACD,MAAM,SAAS,WAAW,iBAAiB;CAE3C,MAAM,QAAQ,cAA+B;EAC3C,MAAM,YAAY,OAAO,CAAC;EAC1B,MAAM,QAAQ,UAAU,SAAS;EACjC,MAAM,OAAO,WAAW,MAAM,KAAK;EACnC,MAAM,qBAAqB,wBAAwB,MAAM,MAAM;EAC/D,MAAM,eAAe,WAAW,oBAAoB,SAAS,KAAK;EAElE,OAAO;GACL,KAAK;GACL;GACA;GACA,QAAQ,SAAS;IAAE,GAAG,OAAO;IAAQ,GAAG;GAAU,IAAI;GACtD;GACA,WAAW,SAAS,QAAQ,WAAW,IAAI;GAC3C,UAAU;GACV,aAAa,SAAS,WAAW,WAAW,MAAM,IAAI,CAAC;GACvD,WAAW,SAAS,WAAW,MAAM,IAAI;GACzC,cAAc,SAAS,iBAAiB,oBAAoB,OAAO,OAAO,IAAI;EAChF;CACF,GAAG;EAAC;EAAM;EAAO;EAAK;EAAU;CAAM,CAAC;CAEvC,OAAO,oBAAC,kBAAkB,UAAnB;EAAmC;EAAQ;CAAqC,CAAA;AACzF;;AAGA,SAAgB,gBAAwC;CACtD,OAAO,WAAW,iBAAiB;AACrC"}
|
|
@@ -3,6 +3,8 @@ import { cn } from "../../../lib/utils.js";
|
|
|
3
3
|
import { Icon } from "../../../icons/sprite.js";
|
|
4
4
|
import { Button } from "../../../core/components/button.js";
|
|
5
5
|
import { Input } from "../base/input.js";
|
|
6
|
+
import { parseTimeString } from "./time-picker-columns.js";
|
|
7
|
+
import { TimePicker } from "./time-picker.js";
|
|
6
8
|
import { formatDateDisplayValue, formatDateTimeDisplayValue, formatDateTimeValue, formatDateValue, formatTimeInputValue, parseDateDisplayValue, parseDateTimeDisplayValue, parseDateTimeValue, parseDateValue } from "./date-picker-value.js";
|
|
7
9
|
import { createElement, useId, useMemo } from "react";
|
|
8
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -166,21 +168,17 @@ function DatePickerControl({ mode, label, name, testId, value, min, max, step, d
|
|
|
166
168
|
})))
|
|
167
169
|
})]
|
|
168
170
|
}),
|
|
169
|
-
mode === "date-time" ? /* @__PURE__ */ jsx(
|
|
170
|
-
|
|
171
|
+
mode === "date-time" ? /* @__PURE__ */ jsx(TimePicker, {
|
|
172
|
+
value: parseTimeString(formatTimeInputValue(selected[0], timezone)),
|
|
173
|
+
onChange: (next) => api.setTime({
|
|
174
|
+
hour: next.hour,
|
|
175
|
+
minute: next.minute,
|
|
176
|
+
second: next.second
|
|
177
|
+
}),
|
|
178
|
+
step,
|
|
171
179
|
disabled,
|
|
172
|
-
onChange: (event) => {
|
|
173
|
-
const [hour = "0", minute = "0", second = "0"] = event.target.value.split(":");
|
|
174
|
-
api.setTime({
|
|
175
|
-
hour: Number(hour),
|
|
176
|
-
minute: Number(minute),
|
|
177
|
-
second: Number(second)
|
|
178
|
-
});
|
|
179
|
-
},
|
|
180
180
|
readOnly,
|
|
181
|
-
|
|
182
|
-
type: "time",
|
|
183
|
-
value: formatTimeInputValue(selected[0], timezone)
|
|
181
|
+
testId: `${testId}-time`
|
|
184
182
|
}) : null
|
|
185
183
|
]
|
|
186
184
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-picker-control.js","names":[],"sources":["../../../../resources/js/form/components/fields/date-picker-control.tsx"],"sourcesContent":["import type { DateValue } from \"@internationalized/date\";\nimport * as datePicker from \"@zag-js/date-picker\";\nimport { normalizeProps, useMachine } from \"@zag-js/react\";\nimport { useId, useMemo } from \"react\";\nimport { Button } from \"@lattice-php/lattice/core/components/button\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { useLocale } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Input } from \"../base/input\";\nimport {\n formatDateDisplayValue,\n formatDateTimeDisplayValue,\n formatDateTimeValue,\n formatDateValue,\n formatTimeInputValue,\n parseDateDisplayValue,\n parseDateTimeDisplayValue,\n parseDateTimeValue,\n parseDateValue,\n} from \"./date-picker-value\";\n\nexport type DatePickerControlProps = {\n mode: \"date\" | \"date-time\";\n label: string;\n name: string;\n testId: string;\n value: unknown;\n min?: string | null;\n max?: string | null;\n step?: number | null;\n disabled: boolean;\n readOnly: boolean;\n autoFocus?: boolean;\n tabIndex?: number | null;\n timezone?: string;\n onChange: (value: string) => void;\n onBlur?: () => void;\n};\n\nexport function DatePickerControl({\n mode,\n label,\n name,\n testId,\n value,\n min,\n max,\n step,\n disabled,\n readOnly,\n autoFocus = false,\n tabIndex,\n timezone = \"UTC\",\n onChange,\n onBlur,\n}: DatePickerControlProps) {\n const id = useId();\n const { locale } = useLocale();\n const selected = useMemo(\n () =>\n [mode === \"date\" ? parseDateValue(value) : parseDateTimeValue(value, timezone)].filter(\n Boolean,\n ) as DateValue[],\n [mode, timezone, value],\n );\n const service = useMachine(datePicker.machine, {\n id,\n name,\n value: selected.length > 0 ? selected : undefined,\n min: min ? parseDateValue(min) : undefined,\n max: max ? parseDateValue(max) : undefined,\n disabled,\n readOnly,\n locale,\n selectionMode: \"single\",\n timeZone: timezone,\n closeOnSelect: mode === \"date\",\n format(date) {\n return mode === \"date\"\n ? formatDateDisplayValue(date, locale)\n : formatDateTimeDisplayValue(date, locale, timezone);\n },\n parse(text) {\n return mode === \"date\"\n ? parseDateDisplayValue(text, locale)\n : parseDateTimeDisplayValue(text, locale, timezone);\n },\n onValueChange(details) {\n const next = details.value[0];\n\n onChange(mode === \"date\" ? formatDateValue(next) : formatDateTimeValue(next, timezone));\n },\n onOpenChange(details) {\n if (!details.open) {\n onBlur?.();\n }\n },\n });\n const api = datePicker.connect(service, normalizeProps);\n const { name: _inputName, onInput, ...inputProps } = api.getInputProps();\n const submittedValue =\n mode === \"date\" ? formatDateValue(selected[0]) : formatDateTimeValue(selected[0], timezone);\n\n return (\n <div {...api.getRootProps()} className={cn(\"relative\", api.open && \"z-lt-popover\")}>\n <input type=\"hidden\" name={name} value={submittedValue} data-test={`${testId}-value`} />\n <div {...api.getControlProps()} className=\"flex gap-2\">\n <Input\n {...inputProps}\n aria-label={label}\n autoFocus={autoFocus}\n data-test={testId}\n disabled={disabled}\n id={name}\n onInput={(event) => {\n onInput?.(event);\n\n if (mode !== \"date\") {\n return;\n }\n\n const normalized = normalizeDateInputValue(event.currentTarget.value);\n\n if (!normalized) {\n return;\n }\n\n const next = parseDateValue(normalized);\n\n if (!next) {\n return;\n }\n\n event.currentTarget.value = normalized;\n api.setValue([next]);\n event.currentTarget.value = formatDateDisplayValue(next, locale);\n onChange(formatDateValue(next));\n }}\n readOnly={readOnly}\n tabIndex={tabIndex ?? undefined}\n />\n <Button\n {...api.getTriggerProps()}\n aria-label={`Open ${label || name} calendar`}\n disabled={disabled || readOnly}\n size=\"icon\"\n type=\"button\"\n variant=\"secondary\"\n >\n <Icon name=\"calendar\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n </div>\n {api.open ? (\n <div\n {...api.getPositionerProps()}\n className=\"absolute z-lt-popover mt-2 rounded-lt-sm border border-lt-border bg-lt-popover p-3 text-lt-popover-fg shadow-lt-md\"\n >\n <div {...api.getContentProps()} className=\"grid gap-3\">\n <div className=\"flex items-center justify-between gap-2\">\n <Button {...api.getPrevTriggerProps()} size=\"icon\" type=\"button\" variant=\"ghost\">\n <Icon name=\"chevron-left\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n <div {...api.getRangeTextProps()} className=\"text-sm font-medium text-lt-fg\" />\n <Button {...api.getNextTriggerProps()} size=\"icon\" type=\"button\" variant=\"ghost\">\n <Icon name=\"chevron-right\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n </div>\n <table {...api.getTableProps()} className=\"w-full border-collapse text-sm\">\n <thead {...api.getTableHeadProps()}>\n <tr {...api.getTableRowProps()}>\n {api.weekDays.map((day) => (\n <th\n {...api.getTableHeaderProps()}\n aria-label={day.long}\n key={day.value.toString()}\n className=\"size-8 text-center text-xs font-medium text-lt-muted-fg\"\n >\n {day.narrow}\n </th>\n ))}\n </tr>\n </thead>\n <tbody {...api.getTableBodyProps()}>\n {api.weeks.map((week, weekIndex) => (\n <tr {...api.getTableRowProps()} key={weekIndex}>\n {week.map((day) => {\n const state = api.getDayTableCellState({ value: day });\n\n return (\n <td\n {...api.getDayTableCellProps({ value: day })}\n key={day.toString()}\n className=\"p-0 text-center\"\n >\n <button\n {...api.getDayTableCellTriggerProps({ value: day })}\n type=\"button\"\n className={cn(\n \"size-8 rounded-lt-sm text-sm text-lt-fg hover:bg-lt-muted\",\n state.selected && \"bg-lt-primary text-lt-primary-fg\",\n state.outsideRange && \"text-lt-muted-fg\",\n state.disabled && \"cursor-not-allowed opacity-40\",\n )}\n >\n {day.day}\n </button>\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n {mode === \"date-time\" ? (\n <Input\n aria-label={`${label || name} time`}\n disabled={disabled}\n onChange={(event) => {\n const [hour = \"0\", minute = \"0\", second = \"0\"] = event.target.value.split(\":\");\n\n api.setTime({\n hour: Number(hour),\n minute: Number(minute),\n second: Number(second),\n });\n }}\n readOnly={readOnly}\n step={step ?? undefined}\n type=\"time\"\n value={formatTimeInputValue(selected[0], timezone)}\n />\n ) : null}\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction normalizeDateInputValue(value: string): string | undefined {\n const compact = value.replace(/\\D/g, \"\");\n\n if (compact.length !== 8) {\n return undefined;\n }\n\n return `${compact.slice(0, 4)}-${compact.slice(4, 6)}-${compact.slice(6, 8)}`;\n}\n"],"mappings":";;;;;;;;;;;AAuCA,SAAgB,kBAAkB,EAChC,MACA,OACA,MACA,QACA,OACA,KACA,KACA,MACA,UACA,UACA,YAAY,OACZ,UACA,WAAW,OACX,UACA,UACyB;CACzB,MAAM,KAAK,MAAM;CACjB,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,WAAW,cAEb,CAAC,SAAS,SAAS,eAAe,KAAK,IAAI,mBAAmB,OAAO,QAAQ,CAAC,EAAE,OAC9E,OACF,GACF;EAAC;EAAM;EAAU;CAAK,CACxB;CACA,MAAM,UAAU,WAAW,WAAW,SAAS;EAC7C;EACA;EACA,OAAO,SAAS,SAAS,IAAI,WAAW,KAAA;EACxC,KAAK,MAAM,eAAe,GAAG,IAAI,KAAA;EACjC,KAAK,MAAM,eAAe,GAAG,IAAI,KAAA;EACjC;EACA;EACA;EACA,eAAe;EACf,UAAU;EACV,eAAe,SAAS;EACxB,OAAO,MAAM;GACX,OAAO,SAAS,SACZ,uBAAuB,MAAM,MAAM,IACnC,2BAA2B,MAAM,QAAQ,QAAQ;EACvD;EACA,MAAM,MAAM;GACV,OAAO,SAAS,SACZ,sBAAsB,MAAM,MAAM,IAClC,0BAA0B,MAAM,QAAQ,QAAQ;EACtD;EACA,cAAc,SAAS;GACrB,MAAM,OAAO,QAAQ,MAAM;GAE3B,SAAS,SAAS,SAAS,gBAAgB,IAAI,IAAI,oBAAoB,MAAM,QAAQ,CAAC;EACxF;EACA,aAAa,SAAS;GACpB,IAAI,CAAC,QAAQ,MACX,SAAS;EAEb;CACF,CAAC;CACD,MAAM,MAAM,WAAW,QAAQ,SAAS,cAAc;CACtD,MAAM,EAAE,MAAM,YAAY,SAAS,GAAG,eAAe,IAAI,cAAc;CACvE,MAAM,iBACJ,SAAS,SAAS,gBAAgB,SAAS,EAAE,IAAI,oBAAoB,SAAS,IAAI,QAAQ;CAE5F,OACE,qBAAC,OAAD;EAAK,GAAI,IAAI,aAAa;EAAG,WAAW,GAAG,YAAY,IAAI,QAAQ,cAAc;YAAjF;GACE,oBAAC,SAAD;IAAO,MAAK;IAAe;IAAM,OAAO;IAAgB,aAAW,GAAG,OAAO;GAAU,CAAA;GACvF,qBAAC,OAAD;IAAK,GAAI,IAAI,gBAAgB;IAAG,WAAU;cAA1C,CACE,oBAAC,OAAD;KACE,GAAI;KACJ,cAAY;KACD;KACX,aAAW;KACD;KACV,IAAI;KACJ,UAAU,UAAU;MAClB,UAAU,KAAK;MAEf,IAAI,SAAS,QACX;MAGF,MAAM,aAAa,wBAAwB,MAAM,cAAc,KAAK;MAEpE,IAAI,CAAC,YACH;MAGF,MAAM,OAAO,eAAe,UAAU;MAEtC,IAAI,CAAC,MACH;MAGF,MAAM,cAAc,QAAQ;MAC5B,IAAI,SAAS,CAAC,IAAI,CAAC;MACnB,MAAM,cAAc,QAAQ,uBAAuB,MAAM,MAAM;MAC/D,SAAS,gBAAgB,IAAI,CAAC;KAChC;KACU;KACV,UAAU,YAAY,KAAA;IACvB,CAAA,GACD,oBAAC,QAAD;KACE,GAAI,IAAI,gBAAgB;KACxB,cAAY,QAAQ,SAAS,KAAK;KAClC,UAAU,YAAY;KACtB,MAAK;KACL,MAAK;KACL,SAAQ;eAER,oBAAC,MAAD;MAAM,MAAK;MAAW,WAAU;MAAkB,eAAY;KAAQ,CAAA;IAChE,CAAA,CACL;;GACJ,IAAI,OACH,oBAAC,OAAD;IACE,GAAI,IAAI,mBAAmB;IAC3B,WAAU;cAEV,qBAAC,OAAD;KAAK,GAAI,IAAI,gBAAgB;KAAG,WAAU;eAA1C;MACE,qBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,oBAAC,QAAD;SAAQ,GAAI,IAAI,oBAAoB;SAAG,MAAK;SAAO,MAAK;SAAS,SAAQ;mBACvE,oBAAC,MAAD;UAAM,MAAK;UAAe,WAAU;UAAkB,eAAY;SAAQ,CAAA;QACpE,CAAA;QACR,oBAAC,OAAD;SAAK,GAAI,IAAI,kBAAkB;SAAG,WAAU;QAAkC,CAAA;QAC9E,oBAAC,QAAD;SAAQ,GAAI,IAAI,oBAAoB;SAAG,MAAK;SAAO,MAAK;SAAS,SAAQ;mBACvE,oBAAC,MAAD;UAAM,MAAK;UAAgB,WAAU;UAAkB,eAAY;SAAQ,CAAA;QACrE,CAAA;OACL;;MACL,qBAAC,SAAD;OAAO,GAAI,IAAI,cAAc;OAAG,WAAU;iBAA1C,CACE,oBAAC,SAAD;QAAO,GAAI,IAAI,kBAAkB;kBAC/B,oBAAC,MAAD;SAAI,GAAI,IAAI,iBAAiB;mBAC1B,IAAI,SAAS,KAAK,QACjB,8BAAC,MAAD;UACE,GAAI,IAAI,oBAAoB;UAC5B,cAAY,IAAI;UAChB,KAAK,IAAI,MAAM,SAAS;UACxB,WAAU;SAGR,GADD,IAAI,MACH,CACL;QACC,CAAA;OACC,CAAA,GACP,oBAAC,SAAD;QAAO,GAAI,IAAI,kBAAkB;kBAC9B,IAAI,MAAM,KAAK,MAAM,cACpB,8BAAC,MAAD;SAAI,GAAI,IAAI,iBAAiB;SAAG,KAAK;QAyBjC,GAxBD,KAAK,KAAK,QAAQ;SACjB,MAAM,QAAQ,IAAI,qBAAqB,EAAE,OAAO,IAAI,CAAC;SAErD,OACE,8BAAC,MAAD;UACE,GAAI,IAAI,qBAAqB,EAAE,OAAO,IAAI,CAAC;UAC3C,KAAK,IAAI,SAAS;UAClB,WAAU;SAcR,GAZF,oBAAC,UAAD;UACE,GAAI,IAAI,4BAA4B,EAAE,OAAO,IAAI,CAAC;UAClD,MAAK;UACL,WAAW,GACT,6DACA,MAAM,YAAY,oCAClB,MAAM,gBAAgB,oBACtB,MAAM,YAAY,+BACpB;oBAEC,IAAI;SACC,CAAA,CACN;QAER,CAAC,CACC,CACL;OACI,CAAA,CACF;;MACN,SAAS,cACR,oBAAC,OAAD;OACE,cAAY,GAAG,SAAS,KAAK;OACnB;OACV,WAAW,UAAU;QACnB,MAAM,CAAC,OAAO,KAAK,SAAS,KAAK,SAAS,OAAO,MAAM,OAAO,MAAM,MAAM,GAAG;QAE7E,IAAI,QAAQ;SACV,MAAM,OAAO,IAAI;SACjB,QAAQ,OAAO,MAAM;SACrB,QAAQ,OAAO,MAAM;QACvB,CAAC;OACH;OACU;OACV,MAAM,QAAQ,KAAA;OACd,MAAK;OACL,OAAO,qBAAqB,SAAS,IAAI,QAAQ;MAClD,CAAA,IACC;KACD;;GACF,CAAA,IACH;EACD;;AAET;AAEA,SAAS,wBAAwB,OAAmC;CAClE,MAAM,UAAU,MAAM,QAAQ,OAAO,EAAE;CAEvC,IAAI,QAAQ,WAAW,GACrB;CAGF,OAAO,GAAG,QAAQ,MAAM,GAAG,CAAC,EAAE,GAAG,QAAQ,MAAM,GAAG,CAAC,EAAE,GAAG,QAAQ,MAAM,GAAG,CAAC;AAC5E"}
|
|
1
|
+
{"version":3,"file":"date-picker-control.js","names":[],"sources":["../../../../resources/js/form/components/fields/date-picker-control.tsx"],"sourcesContent":["import type { DateValue } from \"@internationalized/date\";\nimport * as datePicker from \"@zag-js/date-picker\";\nimport { normalizeProps, useMachine } from \"@zag-js/react\";\nimport { useId, useMemo } from \"react\";\nimport { Button } from \"@lattice-php/lattice/core/components/button\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { useLocale } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Input } from \"../base/input\";\nimport {\n formatDateDisplayValue,\n formatDateTimeDisplayValue,\n formatDateTimeValue,\n formatDateValue,\n formatTimeInputValue,\n parseDateDisplayValue,\n parseDateTimeDisplayValue,\n parseDateTimeValue,\n parseDateValue,\n} from \"./date-picker-value\";\nimport { TimePicker } from \"./time-picker\";\nimport { parseTimeString } from \"./time-picker-columns\";\n\nexport type DatePickerControlProps = {\n mode: \"date\" | \"date-time\";\n label: string;\n name: string;\n testId: string;\n value: unknown;\n min?: string | null;\n max?: string | null;\n step?: number | null;\n disabled: boolean;\n readOnly: boolean;\n autoFocus?: boolean;\n tabIndex?: number | null;\n timezone?: string;\n onChange: (value: string) => void;\n onBlur?: () => void;\n};\n\nexport function DatePickerControl({\n mode,\n label,\n name,\n testId,\n value,\n min,\n max,\n step,\n disabled,\n readOnly,\n autoFocus = false,\n tabIndex,\n timezone = \"UTC\",\n onChange,\n onBlur,\n}: DatePickerControlProps) {\n const id = useId();\n const { locale } = useLocale();\n const selected = useMemo(\n () =>\n [mode === \"date\" ? parseDateValue(value) : parseDateTimeValue(value, timezone)].filter(\n Boolean,\n ) as DateValue[],\n [mode, timezone, value],\n );\n const service = useMachine(datePicker.machine, {\n id,\n name,\n value: selected.length > 0 ? selected : undefined,\n min: min ? parseDateValue(min) : undefined,\n max: max ? parseDateValue(max) : undefined,\n disabled,\n readOnly,\n locale,\n selectionMode: \"single\",\n timeZone: timezone,\n closeOnSelect: mode === \"date\",\n format(date) {\n return mode === \"date\"\n ? formatDateDisplayValue(date, locale)\n : formatDateTimeDisplayValue(date, locale, timezone);\n },\n parse(text) {\n return mode === \"date\"\n ? parseDateDisplayValue(text, locale)\n : parseDateTimeDisplayValue(text, locale, timezone);\n },\n onValueChange(details) {\n const next = details.value[0];\n\n onChange(mode === \"date\" ? formatDateValue(next) : formatDateTimeValue(next, timezone));\n },\n onOpenChange(details) {\n if (!details.open) {\n onBlur?.();\n }\n },\n });\n const api = datePicker.connect(service, normalizeProps);\n const { name: _inputName, onInput, ...inputProps } = api.getInputProps();\n const submittedValue =\n mode === \"date\" ? formatDateValue(selected[0]) : formatDateTimeValue(selected[0], timezone);\n\n return (\n <div {...api.getRootProps()} className={cn(\"relative\", api.open && \"z-lt-popover\")}>\n <input type=\"hidden\" name={name} value={submittedValue} data-test={`${testId}-value`} />\n <div {...api.getControlProps()} className=\"flex gap-2\">\n <Input\n {...inputProps}\n aria-label={label}\n autoFocus={autoFocus}\n data-test={testId}\n disabled={disabled}\n id={name}\n onInput={(event) => {\n onInput?.(event);\n\n if (mode !== \"date\") {\n return;\n }\n\n const normalized = normalizeDateInputValue(event.currentTarget.value);\n\n if (!normalized) {\n return;\n }\n\n const next = parseDateValue(normalized);\n\n if (!next) {\n return;\n }\n\n event.currentTarget.value = normalized;\n api.setValue([next]);\n event.currentTarget.value = formatDateDisplayValue(next, locale);\n onChange(formatDateValue(next));\n }}\n readOnly={readOnly}\n tabIndex={tabIndex ?? undefined}\n />\n <Button\n {...api.getTriggerProps()}\n aria-label={`Open ${label || name} calendar`}\n disabled={disabled || readOnly}\n size=\"icon\"\n type=\"button\"\n variant=\"secondary\"\n >\n <Icon name=\"calendar\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n </div>\n {api.open ? (\n <div\n {...api.getPositionerProps()}\n className=\"absolute z-lt-popover mt-2 rounded-lt-sm border border-lt-border bg-lt-popover p-3 text-lt-popover-fg shadow-lt-md\"\n >\n <div {...api.getContentProps()} className=\"grid gap-3\">\n <div className=\"flex items-center justify-between gap-2\">\n <Button {...api.getPrevTriggerProps()} size=\"icon\" type=\"button\" variant=\"ghost\">\n <Icon name=\"chevron-left\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n <div {...api.getRangeTextProps()} className=\"text-sm font-medium text-lt-fg\" />\n <Button {...api.getNextTriggerProps()} size=\"icon\" type=\"button\" variant=\"ghost\">\n <Icon name=\"chevron-right\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n </div>\n <table {...api.getTableProps()} className=\"w-full border-collapse text-sm\">\n <thead {...api.getTableHeadProps()}>\n <tr {...api.getTableRowProps()}>\n {api.weekDays.map((day) => (\n <th\n {...api.getTableHeaderProps()}\n aria-label={day.long}\n key={day.value.toString()}\n className=\"size-8 text-center text-xs font-medium text-lt-muted-fg\"\n >\n {day.narrow}\n </th>\n ))}\n </tr>\n </thead>\n <tbody {...api.getTableBodyProps()}>\n {api.weeks.map((week, weekIndex) => (\n <tr {...api.getTableRowProps()} key={weekIndex}>\n {week.map((day) => {\n const state = api.getDayTableCellState({ value: day });\n\n return (\n <td\n {...api.getDayTableCellProps({ value: day })}\n key={day.toString()}\n className=\"p-0 text-center\"\n >\n <button\n {...api.getDayTableCellTriggerProps({ value: day })}\n type=\"button\"\n className={cn(\n \"size-8 rounded-lt-sm text-sm text-lt-fg hover:bg-lt-muted\",\n state.selected && \"bg-lt-primary text-lt-primary-fg\",\n state.outsideRange && \"text-lt-muted-fg\",\n state.disabled && \"cursor-not-allowed opacity-40\",\n )}\n >\n {day.day}\n </button>\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n {mode === \"date-time\" ? (\n <TimePicker\n value={parseTimeString(formatTimeInputValue(selected[0], timezone))}\n onChange={(next) =>\n api.setTime({ hour: next.hour, minute: next.minute, second: next.second })\n }\n step={step}\n disabled={disabled}\n readOnly={readOnly}\n testId={`${testId}-time`}\n />\n ) : null}\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction normalizeDateInputValue(value: string): string | undefined {\n const compact = value.replace(/\\D/g, \"\");\n\n if (compact.length !== 8) {\n return undefined;\n }\n\n return `${compact.slice(0, 4)}-${compact.slice(4, 6)}-${compact.slice(6, 8)}`;\n}\n"],"mappings":";;;;;;;;;;;;;AAyCA,SAAgB,kBAAkB,EAChC,MACA,OACA,MACA,QACA,OACA,KACA,KACA,MACA,UACA,UACA,YAAY,OACZ,UACA,WAAW,OACX,UACA,UACyB;CACzB,MAAM,KAAK,MAAM;CACjB,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,WAAW,cAEb,CAAC,SAAS,SAAS,eAAe,KAAK,IAAI,mBAAmB,OAAO,QAAQ,CAAC,EAAE,OAC9E,OACF,GACF;EAAC;EAAM;EAAU;CAAK,CACxB;CACA,MAAM,UAAU,WAAW,WAAW,SAAS;EAC7C;EACA;EACA,OAAO,SAAS,SAAS,IAAI,WAAW,KAAA;EACxC,KAAK,MAAM,eAAe,GAAG,IAAI,KAAA;EACjC,KAAK,MAAM,eAAe,GAAG,IAAI,KAAA;EACjC;EACA;EACA;EACA,eAAe;EACf,UAAU;EACV,eAAe,SAAS;EACxB,OAAO,MAAM;GACX,OAAO,SAAS,SACZ,uBAAuB,MAAM,MAAM,IACnC,2BAA2B,MAAM,QAAQ,QAAQ;EACvD;EACA,MAAM,MAAM;GACV,OAAO,SAAS,SACZ,sBAAsB,MAAM,MAAM,IAClC,0BAA0B,MAAM,QAAQ,QAAQ;EACtD;EACA,cAAc,SAAS;GACrB,MAAM,OAAO,QAAQ,MAAM;GAE3B,SAAS,SAAS,SAAS,gBAAgB,IAAI,IAAI,oBAAoB,MAAM,QAAQ,CAAC;EACxF;EACA,aAAa,SAAS;GACpB,IAAI,CAAC,QAAQ,MACX,SAAS;EAEb;CACF,CAAC;CACD,MAAM,MAAM,WAAW,QAAQ,SAAS,cAAc;CACtD,MAAM,EAAE,MAAM,YAAY,SAAS,GAAG,eAAe,IAAI,cAAc;CACvE,MAAM,iBACJ,SAAS,SAAS,gBAAgB,SAAS,EAAE,IAAI,oBAAoB,SAAS,IAAI,QAAQ;CAE5F,OACE,qBAAC,OAAD;EAAK,GAAI,IAAI,aAAa;EAAG,WAAW,GAAG,YAAY,IAAI,QAAQ,cAAc;YAAjF;GACE,oBAAC,SAAD;IAAO,MAAK;IAAe;IAAM,OAAO;IAAgB,aAAW,GAAG,OAAO;GAAU,CAAA;GACvF,qBAAC,OAAD;IAAK,GAAI,IAAI,gBAAgB;IAAG,WAAU;cAA1C,CACE,oBAAC,OAAD;KACE,GAAI;KACJ,cAAY;KACD;KACX,aAAW;KACD;KACV,IAAI;KACJ,UAAU,UAAU;MAClB,UAAU,KAAK;MAEf,IAAI,SAAS,QACX;MAGF,MAAM,aAAa,wBAAwB,MAAM,cAAc,KAAK;MAEpE,IAAI,CAAC,YACH;MAGF,MAAM,OAAO,eAAe,UAAU;MAEtC,IAAI,CAAC,MACH;MAGF,MAAM,cAAc,QAAQ;MAC5B,IAAI,SAAS,CAAC,IAAI,CAAC;MACnB,MAAM,cAAc,QAAQ,uBAAuB,MAAM,MAAM;MAC/D,SAAS,gBAAgB,IAAI,CAAC;KAChC;KACU;KACV,UAAU,YAAY,KAAA;IACvB,CAAA,GACD,oBAAC,QAAD;KACE,GAAI,IAAI,gBAAgB;KACxB,cAAY,QAAQ,SAAS,KAAK;KAClC,UAAU,YAAY;KACtB,MAAK;KACL,MAAK;KACL,SAAQ;eAER,oBAAC,MAAD;MAAM,MAAK;MAAW,WAAU;MAAkB,eAAY;KAAQ,CAAA;IAChE,CAAA,CACL;;GACJ,IAAI,OACH,oBAAC,OAAD;IACE,GAAI,IAAI,mBAAmB;IAC3B,WAAU;cAEV,qBAAC,OAAD;KAAK,GAAI,IAAI,gBAAgB;KAAG,WAAU;eAA1C;MACE,qBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,oBAAC,QAAD;SAAQ,GAAI,IAAI,oBAAoB;SAAG,MAAK;SAAO,MAAK;SAAS,SAAQ;mBACvE,oBAAC,MAAD;UAAM,MAAK;UAAe,WAAU;UAAkB,eAAY;SAAQ,CAAA;QACpE,CAAA;QACR,oBAAC,OAAD;SAAK,GAAI,IAAI,kBAAkB;SAAG,WAAU;QAAkC,CAAA;QAC9E,oBAAC,QAAD;SAAQ,GAAI,IAAI,oBAAoB;SAAG,MAAK;SAAO,MAAK;SAAS,SAAQ;mBACvE,oBAAC,MAAD;UAAM,MAAK;UAAgB,WAAU;UAAkB,eAAY;SAAQ,CAAA;QACrE,CAAA;OACL;;MACL,qBAAC,SAAD;OAAO,GAAI,IAAI,cAAc;OAAG,WAAU;iBAA1C,CACE,oBAAC,SAAD;QAAO,GAAI,IAAI,kBAAkB;kBAC/B,oBAAC,MAAD;SAAI,GAAI,IAAI,iBAAiB;mBAC1B,IAAI,SAAS,KAAK,QACjB,8BAAC,MAAD;UACE,GAAI,IAAI,oBAAoB;UAC5B,cAAY,IAAI;UAChB,KAAK,IAAI,MAAM,SAAS;UACxB,WAAU;SAGR,GADD,IAAI,MACH,CACL;QACC,CAAA;OACC,CAAA,GACP,oBAAC,SAAD;QAAO,GAAI,IAAI,kBAAkB;kBAC9B,IAAI,MAAM,KAAK,MAAM,cACpB,8BAAC,MAAD;SAAI,GAAI,IAAI,iBAAiB;SAAG,KAAK;QAyBjC,GAxBD,KAAK,KAAK,QAAQ;SACjB,MAAM,QAAQ,IAAI,qBAAqB,EAAE,OAAO,IAAI,CAAC;SAErD,OACE,8BAAC,MAAD;UACE,GAAI,IAAI,qBAAqB,EAAE,OAAO,IAAI,CAAC;UAC3C,KAAK,IAAI,SAAS;UAClB,WAAU;SAcR,GAZF,oBAAC,UAAD;UACE,GAAI,IAAI,4BAA4B,EAAE,OAAO,IAAI,CAAC;UAClD,MAAK;UACL,WAAW,GACT,6DACA,MAAM,YAAY,oCAClB,MAAM,gBAAgB,oBACtB,MAAM,YAAY,+BACpB;oBAEC,IAAI;SACC,CAAA,CACN;QAER,CAAC,CACC,CACL;OACI,CAAA,CACF;;MACN,SAAS,cACR,oBAAC,YAAD;OACE,OAAO,gBAAgB,qBAAqB,SAAS,IAAI,QAAQ,CAAC;OAClE,WAAW,SACT,IAAI,QAAQ;QAAE,MAAM,KAAK;QAAM,QAAQ,KAAK;QAAQ,QAAQ,KAAK;OAAO,CAAC;OAErE;OACI;OACA;OACV,QAAQ,GAAG,OAAO;MACnB,CAAA,IACC;KACD;;GACF,CAAA,IACH;EACD;;AAET;AAEA,SAAS,wBAAwB,OAAmC;CAClE,MAAM,UAAU,MAAM,QAAQ,OAAO,EAAE;CAEvC,IAAI,QAAQ,WAAW,GACrB;CAGF,OAAO,GAAG,QAAQ,MAAM,GAAG,CAAC,EAAE,GAAG,QAAQ,MAAM,GAAG,CAAC,EAAE,GAAG,QAAQ,MAAM,GAAG,CAAC;AAC5E"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RowAction as WireRowAction } from '../../../types/generated';
|
|
2
2
|
import { RowAction } from './row-actions';
|
|
3
|
-
|
|
3
|
+
type RowActionTranslate = (key: string, fallback: string) => string;
|
|
4
4
|
export type RowActionContext = {
|
|
5
5
|
index: number;
|
|
6
6
|
removable: boolean;
|
|
@@ -15,3 +15,4 @@ export type RowActionContext = {
|
|
|
15
15
|
* minimum, and built-in labels resolve through i18n when the server sends none.
|
|
16
16
|
*/
|
|
17
17
|
export declare function buildRowActions(declared: WireRowAction[] | null, ctx: RowActionContext): RowAction[];
|
|
18
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"row-action-menu.js","names":[],"sources":["../../../../resources/js/form/components/fields/row-action-menu.ts"],"sourcesContent":["import type { RowAction as WireRowAction } from \"@lattice-php/lattice/types/generated\";\nimport type { RowAction } from \"./row-actions\";\n\
|
|
1
|
+
{"version":3,"file":"row-action-menu.js","names":[],"sources":["../../../../resources/js/form/components/fields/row-action-menu.ts"],"sourcesContent":["import type { RowAction as WireRowAction } from \"@lattice-php/lattice/types/generated\";\nimport type { RowAction } from \"./row-actions\";\n\ntype RowActionTranslate = (key: string, fallback: string) => string;\n\n/** Translation key + fallback and icon for each built-in; the server sends null labels. */\nconst BUILT_IN: Record<\"duplicate\" | \"remove\", { key: string; fallback: string; icon: string }> = {\n duplicate: { key: \"table.rowActions.duplicate\", fallback: \"Duplicate\", icon: \"copy\" },\n remove: { key: \"table.rowActions.remove\", fallback: \"Remove\", icon: \"trash-2\" },\n};\n\nexport type RowActionContext = {\n index: number;\n removable: boolean;\n onRemove: (index: number) => void;\n onDuplicate: (index: number) => void;\n t: RowActionTranslate;\n};\n\n/**\n * Resolves the declared wire row actions into the click-wired client actions the\n * kebab renders. `null` (undeclared) falls back to the built-in remove; an empty\n * array disables row actions entirely. Remove is dropped while the row is at its\n * minimum, and built-in labels resolve through i18n when the server sends none.\n */\nexport function buildRowActions(\n declared: WireRowAction[] | null,\n ctx: RowActionContext,\n): RowAction[] {\n const source = declared ?? defaultActions(ctx.removable);\n\n return source\n .map((action) => toClientAction(action, ctx))\n .filter((action): action is RowAction => action !== null);\n}\n\nfunction defaultActions(removable: boolean): WireRowAction[] {\n if (!removable) {\n return [];\n }\n\n return [{ type: \"remove\", key: \"remove\", label: null, icon: null, destructive: true }];\n}\n\nfunction toClientAction(action: WireRowAction, ctx: RowActionContext): RowAction | null {\n if (action.type === \"duplicate\") {\n const builtIn = BUILT_IN.duplicate;\n\n return {\n key: action.key,\n label: action.label ?? ctx.t(builtIn.key, builtIn.fallback),\n icon: action.icon ?? builtIn.icon,\n destructive: action.destructive,\n onClick: () => ctx.onDuplicate(ctx.index),\n };\n }\n\n if (action.type === \"remove\") {\n if (!ctx.removable) {\n return null;\n }\n\n const builtIn = BUILT_IN.remove;\n\n return {\n key: action.key,\n label: action.label ?? ctx.t(builtIn.key, builtIn.fallback),\n icon: action.icon ?? builtIn.icon,\n destructive: action.destructive,\n onClick: () => ctx.onRemove(ctx.index),\n };\n }\n\n return null;\n}\n"],"mappings":";;AAMA,IAAM,WAA4F;CAChG,WAAW;EAAE,KAAK;EAA8B,UAAU;EAAa,MAAM;CAAO;CACpF,QAAQ;EAAE,KAAK;EAA2B,UAAU;EAAU,MAAM;CAAU;AAChF;;;;;;;AAgBA,SAAgB,gBACd,UACA,KACa;CAGb,QAFe,YAAY,eAAe,IAAI,SAAS,GAGpD,KAAK,WAAW,eAAe,QAAQ,GAAG,CAAC,EAC3C,QAAQ,WAAgC,WAAW,IAAI;AAC5D;AAEA,SAAS,eAAe,WAAqC;CAC3D,IAAI,CAAC,WACH,OAAO,CAAC;CAGV,OAAO,CAAC;EAAE,MAAM;EAAU,KAAK;EAAU,OAAO;EAAM,MAAM;EAAM,aAAa;CAAK,CAAC;AACvF;AAEA,SAAS,eAAe,QAAuB,KAAyC;CACtF,IAAI,OAAO,SAAS,aAAa;EAC/B,MAAM,UAAU,SAAS;EAEzB,OAAO;GACL,KAAK,OAAO;GACZ,OAAO,OAAO,SAAS,IAAI,EAAE,QAAQ,KAAK,QAAQ,QAAQ;GAC1D,MAAM,OAAO,QAAQ,QAAQ;GAC7B,aAAa,OAAO;GACpB,eAAe,IAAI,YAAY,IAAI,KAAK;EAC1C;CACF;CAEA,IAAI,OAAO,SAAS,UAAU;EAC5B,IAAI,CAAC,IAAI,WACP,OAAO;EAGT,MAAM,UAAU,SAAS;EAEzB,OAAO;GACL,KAAK,OAAO;GACZ,OAAO,OAAO,SAAS,IAAI,EAAE,QAAQ,KAAK,QAAQ,QAAQ;GAC1D,MAAM,OAAO,QAAQ,QAAQ;GAC7B,aAAa,OAAO;GACpB,eAAe,IAAI,SAAS,IAAI,KAAK;EACvC;CACF;CAEA,OAAO;AACT"}
|
|
@@ -8,7 +8,7 @@ export declare function RowButton({ label, testId, onClick, children, }: {
|
|
|
8
8
|
onClick: () => void;
|
|
9
9
|
children: ReactNode;
|
|
10
10
|
}): import("react").JSX.Element;
|
|
11
|
-
|
|
11
|
+
type RowItemProps = {
|
|
12
12
|
base: string;
|
|
13
13
|
index: number;
|
|
14
14
|
row: RepeaterRow;
|
|
@@ -25,3 +25,4 @@ export type RowItemProps = {
|
|
|
25
25
|
onDuplicate: (index: number) => void;
|
|
26
26
|
};
|
|
27
27
|
export declare const RowItem: import('react').MemoExoticComponent<({ base, index, row, template, heading, reorderable, isFirst, isLast, removable, rowActions, onField, onRemove, onMove, onDuplicate, }: RowItemProps) => import("react").JSX.Element>;
|
|
28
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"row-item.js","names":[],"sources":["../../../../resources/js/form/components/fields/row-item.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport type { ReactNode } from \"react\";\nimport { memo } from \"react\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { RowAction as WireRowAction } from \"@lattice-php/lattice/types/generated\";\nimport { FieldScopeProvider } from \"../field-scope\";\nimport { buildRowActions } from \"./row-action-menu\";\nimport { RowActions } from \"./row-actions\";\nimport type { RepeaterRow } from \"./repeater-rows\";\n\nexport function RowButton({\n label,\n testId,\n onClick,\n children,\n}: {\n label: string;\n testId: string;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n data-test={testId}\n className=\"text-lt-muted-fg hover:text-lt-fg\"\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n\
|
|
1
|
+
{"version":3,"file":"row-item.js","names":[],"sources":["../../../../resources/js/form/components/fields/row-item.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport type { ReactNode } from \"react\";\nimport { memo } from \"react\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { RowAction as WireRowAction } from \"@lattice-php/lattice/types/generated\";\nimport { FieldScopeProvider } from \"../field-scope\";\nimport { buildRowActions } from \"./row-action-menu\";\nimport { RowActions } from \"./row-actions\";\nimport type { RepeaterRow } from \"./repeater-rows\";\n\nexport function RowButton({\n label,\n testId,\n onClick,\n children,\n}: {\n label: string;\n testId: string;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n data-test={testId}\n className=\"text-lt-muted-fg hover:text-lt-fg\"\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n\ntype RowItemProps = {\n base: string;\n index: number;\n row: RepeaterRow;\n template: Node[];\n heading: string;\n reorderable: boolean;\n isFirst: boolean;\n isLast: boolean;\n removable: boolean;\n rowActions: WireRowAction[] | null;\n onField: (index: number, field: string, value: unknown) => void;\n onRemove: (index: number) => void;\n onMove: (index: number, delta: number) => void;\n onDuplicate: (index: number) => void;\n};\n\n// Memoised so editing one row doesn't re-render its siblings. Its props are kept\n// referentially stable by the parent: `row` survives untouched via functional\n// store updates, and the handlers are `useCallback`-stable.\nexport const RowItem = memo(function RowItem({\n base,\n index,\n row,\n template,\n heading,\n reorderable,\n isFirst,\n isLast,\n removable,\n rowActions,\n onField,\n onRemove,\n onMove,\n onDuplicate,\n}: RowItemProps) {\n const { t } = useT(\"lattice\");\n\n return (\n <div\n data-test={`repeater-${base}-row-${index}`}\n className=\"rounded-lt border border-lt-border bg-lt-surface p-4\"\n >\n <div className=\"mb-2 flex items-center justify-between\">\n <span className=\"text-sm font-medium text-lt-muted-fg\">{heading}</span>\n <div className=\"flex items-center gap-1 [&_svg]:size-lt-icon-sm\">\n {reorderable && !isFirst && (\n <RowButton\n label=\"Move up\"\n testId={`repeater-${base}-up-${index}`}\n onClick={() => onMove(index, -1)}\n >\n <Icon name=\"arrow-up\" />\n </RowButton>\n )}\n {reorderable && !isLast && (\n <RowButton\n label=\"Move down\"\n testId={`repeater-${base}-down-${index}`}\n onClick={() => onMove(index, 1)}\n >\n <Icon name=\"arrow-down\" />\n </RowButton>\n )}\n <RowActions\n actions={buildRowActions(rowActions, { index, removable, onRemove, onDuplicate, t })}\n />\n </div>\n </div>\n\n <FieldScopeProvider\n base={base}\n index={index}\n row={row}\n onChange={(field, value) => onField(index, field, value)}\n >\n <div className=\"flex flex-col gap-4\">\n {template.map((child) => (\n <RenderNode key={child.key ?? child.id} node={child} />\n ))}\n </div>\n </FieldScopeProvider>\n </div>\n );\n});\n"],"mappings":";;;;;;;;;AAYA,SAAgB,UAAU,EACxB,OACA,QACA,SACA,YAMC;CACD,OACE,oBAAC,UAAD;EACE,MAAK;EACL,cAAY;EACZ,aAAW;EACX,WAAU;EACD;EAER;CACK,CAAA;AAEZ;AAsBA,IAAa,UAAU,KAAK,SAAS,QAAQ,EAC3C,MACA,OACA,KACA,UACA,SACA,aACA,SACA,QACA,WACA,YACA,SACA,UACA,QACA,eACe;CACf,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,OACE,qBAAC,OAAD;EACE,aAAW,YAAY,KAAK,OAAO;EACnC,WAAU;YAFZ,CAIE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,QAAD;IAAM,WAAU;cAAwC;GAAc,CAAA,GACtE,qBAAC,OAAD;IAAK,WAAU;cAAf;KACG,eAAe,CAAC,WACf,oBAAC,WAAD;MACE,OAAM;MACN,QAAQ,YAAY,KAAK,MAAM;MAC/B,eAAe,OAAO,OAAO,EAAE;gBAE/B,oBAAC,MAAD,EAAM,MAAK,WAAY,CAAA;KACd,CAAA;KAEZ,eAAe,CAAC,UACf,oBAAC,WAAD;MACE,OAAM;MACN,QAAQ,YAAY,KAAK,QAAQ;MACjC,eAAe,OAAO,OAAO,CAAC;gBAE9B,oBAAC,MAAD,EAAM,MAAK,aAAc,CAAA;KAChB,CAAA;KAEb,oBAAC,YAAD,EACE,SAAS,gBAAgB,YAAY;MAAE;MAAO;MAAW;MAAU;MAAa;KAAE,CAAC,EACpF,CAAA;IACE;KACF;MAEL,oBAAC,oBAAD;GACQ;GACC;GACF;GACL,WAAW,OAAO,UAAU,QAAQ,OAAO,OAAO,KAAK;aAEvD,oBAAC,OAAD;IAAK,WAAU;cACZ,SAAS,KAAK,UACb,oBAAC,YAAD,EAAwC,MAAM,MAAQ,GAArC,MAAM,OAAO,MAAM,EAAkB,CACvD;GACE,CAAA;EACa,CAAA,CACjB;;AAET,CAAC"}
|
|
@@ -6,7 +6,7 @@ export type TableColumn = {
|
|
|
6
6
|
label: string;
|
|
7
7
|
columnWidth: ColumnWidth;
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
type TableRowModel = {
|
|
10
10
|
key: string;
|
|
11
11
|
index: number;
|
|
12
12
|
row: RepeaterRow;
|
|
@@ -30,3 +30,4 @@ export declare function TableRows({ base, columns, rows, reorderable, removable,
|
|
|
30
30
|
resizableColumns?: boolean;
|
|
31
31
|
resizeIndicator?: boolean;
|
|
32
32
|
}): import("react").JSX.Element;
|
|
33
|
+
export {};
|