@alfakit/core 0.1.2 → 0.1.7
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/CHANGELOG.md +12 -0
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +6 -0
- package/dist/actions.js.map +1 -1
- package/dist/advanced-fields.js +2 -2
- package/dist/advanced-fields.js.map +1 -1
- package/dist/assets.d.ts.map +1 -1
- package/dist/assets.js +2 -1
- package/dist/assets.js.map +1 -1
- package/dist/csp.d.ts +11 -0
- package/dist/csp.d.ts.map +1 -0
- package/dist/csp.js +16 -0
- package/dist/csp.js.map +1 -0
- package/dist/form.d.ts +20 -0
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +49 -4
- package/dist/form.js.map +1 -1
- package/dist/icons.d.ts +6 -0
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +9 -1
- package/dist/icons.js.map +1 -1
- package/dist/image-editor.d.ts +2 -2
- package/dist/image-editor.js +2 -2
- package/dist/image-files.d.ts +8 -0
- package/dist/image-files.d.ts.map +1 -1
- package/dist/image-files.js +11 -1
- package/dist/image-files.js.map +1 -1
- package/dist/index.d.ts +10 -9
- package/dist/index.js +8 -7
- package/dist/kanban.d.ts.map +1 -1
- package/dist/kanban.js +1 -1
- package/dist/kanban.js.map +1 -1
- package/dist/page-actions.d.ts +2 -2
- package/dist/page-actions.d.ts.map +1 -1
- package/dist/page-actions.js +4 -4
- package/dist/page-actions.js.map +1 -1
- package/dist/schema/advanced-fields.d.ts +5 -0
- package/dist/schema/advanced-fields.d.ts.map +1 -1
- package/dist/schema/cms.d.ts +2 -0
- package/dist/schema/cms.d.ts.map +1 -1
- package/dist/schema/index.d.ts +3 -3
- package/dist/schema/panel.d.ts +25 -0
- package/dist/schema/panel.d.ts.map +1 -1
- package/dist/schema/panel.js.map +1 -1
- package/dist/standalone.d.ts +10 -3
- package/dist/standalone.d.ts.map +1 -1
- package/dist/standalone.js +12 -2
- package/dist/standalone.js.map +1 -1
- package/dist/starter-kit-widgets.d.ts +40 -7
- package/dist/starter-kit-widgets.d.ts.map +1 -1
- package/dist/starter-kit-widgets.js +71 -7
- package/dist/starter-kit-widgets.js.map +1 -1
- package/dist/starter-kit.d.ts +24 -1
- package/dist/starter-kit.d.ts.map +1 -1
- package/dist/starter-kit.js +33 -3
- package/dist/starter-kit.js.map +1 -1
- package/dist/utils/debounce.d.ts +2 -0
- package/dist/utils/debounce.d.ts.map +1 -1
- package/dist/utils/debounce.js +1 -0
- package/dist/utils/debounce.js.map +1 -1
- package/dist/utils/path.d.ts +11 -1
- package/dist/utils/path.d.ts.map +1 -1
- package/dist/utils/path.js +30 -3
- package/dist/utils/path.js.map +1 -1
- package/package.json +1 -1
- package/themes.css +6 -1
package/dist/starter-kit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"starter-kit.js","names":[],"sources":["../src/starter-kit.ts"],"sourcesContent":["import { debugRecorder } from './debug'\nimport {\n effectiveErrorNotifications,\n installErrorNotifications,\n resolveRequestErrorNotification,\n setRequestErrorReporter,\n} from './error-notifications'\nimport { reloadOnExpiredPage } from './http'\nimport { navigationItemText } from './navigation'\nimport type { NotificationSchema } from './schema/notifications'\nimport type {\n AlfakitPageProps,\n BreadcrumbSchema,\n ErrorNotificationsSchema,\n NavigationGroupSchema,\n NavigationItemSchema,\n PanelSchema,\n StarterKitNavigationSchema,\n} from './schema/panel'\nimport { installSpaUrlExceptions } from './spa'\n\n/**\n * Starter kit mode (`Panel::starterKit()`): Alfakit pages render inside an application made\n * from Laravel's React, Vue or Svelte starter kit, in the host's own layout. These helpers are\n * shared by the three renderers; the host's sidebar reads the navigation through each\n * renderer's `useAlfakitNavigation()`.\n */\n\n/**\n * The sonner toaster Alfakit renders in starter kit mode. The host layout mounts its own\n * id-less `<Toaster />`; giving Alfakit's an id keeps each toast in one toaster even when the\n * host and Alfakit resolve the same sonner instance.\n */\nexport const STARTER_KIT_TOASTER_ID = 'alfakit'\n\n/** Whether the panel runs inside a starter kit application (`Panel::starterKit()`). */\nexport function isStarterKitPanel(\n panel: Pick<PanelSchema, 'starterKit'> | null | undefined,\n): boolean {\n return panel?.starterKit === true\n}\n\n/** A breadcrumb as the starter kits' `AppLayout` takes it (`BreadcrumbItem`). */\nexport interface StarterKitBreadcrumb {\n title: string\n href: string\n}\n\n/**\n * The page's breadcrumbs in the starter kits' shape: `{ title, href }` instead of\n * `{ label, url }`. The kits render the last crumb (the current page) as plain text and key\n * the list by `href`, so every `href` is unique: the last crumb without a URL keeps an empty\n * one, other crumbs without one (or repeating one) get a `#index` fragment.\n */\nexport function toStarterKitBreadcrumbs(\n breadcrumbs: BreadcrumbSchema[] | null | undefined,\n): StarterKitBreadcrumb[] {\n const list = breadcrumbs ?? []\n const seen = new Set<string>()\n\n return list.map((crumb, index) => {\n let href = crumb.url ?? (index === list.length - 1 ? '' : `#${index}`)\n\n if (seen.has(href)) href = `${href}#${index}`\n\n seen.add(href)\n\n return { title: crumb.label, href }\n })\n}\n\n/** The breadcrumbs of an Alfakit page from its Inertia props (`props.page.breadcrumbs`). */\nexport function starterKitBreadcrumbsFromProps(props: unknown): StarterKitBreadcrumb[] {\n const page = (props as { page?: { breadcrumbs?: BreadcrumbSchema[] } } | null | undefined)?.page\n\n return toStarterKitBreadcrumbs(page?.breadcrumbs)\n}\n\n/**\n * The shared `alfakitNavigation` prop of a page: one entry per `starterKit()` panel, or none\n * for guests and pages of other panels.\n */\nexport function starterKitNavigations(props: unknown): StarterKitNavigationSchema[] {\n const value = (props as { alfakitNavigation?: unknown } | null | undefined)?.alfakitNavigation\n\n return Array.isArray(value) ? (value as StarterKitNavigationSchema[]) : []\n}\n\n/** One panel's navigation (the first starter kit panel when no id is given), or null. */\nexport function starterKitNavigation(\n props: unknown,\n panelId?: string,\n): StarterKitNavigationSchema | null {\n const navigations = starterKitNavigations(props)\n\n return (\n (panelId === undefined\n ? navigations[0]\n : navigations.find((navigation) => navigation.id === panelId)) ?? null\n )\n}\n\n/**\n * A navigation item flattened for a starter kit sidebar: the label as text and the item's\n * nested children. `title`/`href` match the kits' `NavItem` so the host can reuse its types.\n */\nexport interface StarterKitNavItem {\n key: string\n title: string\n href: string\n icon?: string\n isActive: boolean\n openInNewTab: boolean\n badge?: string | number\n badgeColor?: string\n badgeTooltip?: string\n children: StarterKitNavItem[]\n}\n\nexport interface StarterKitNavGroup {\n key: string\n label: string | null\n icon?: string\n items: StarterKitNavItem[]\n}\n\nfunction toNavItem(item: NavigationItemSchema, key: string): StarterKitNavItem {\n return {\n key,\n title: navigationItemText(item),\n href: item.url ?? '',\n icon: item.icon ?? undefined,\n isActive: item.active === true,\n openInNewTab: item.openInNewTab === true,\n badge: item.badge ?? undefined,\n badgeColor: item.badgeColor ?? undefined,\n badgeTooltip: item.badgeTooltip ?? undefined,\n children: (item.children ?? []).map((child, index) => toNavItem(child, `${key}.${index}`)),\n }\n}\n\n/** A panel's navigation groups as plain items for the host's sidebar primitives. */\nexport function toStarterKitNavGroups(\n groups: NavigationGroupSchema[] | null | undefined,\n): StarterKitNavGroup[] {\n return (groups ?? []).map((group, index) => {\n const key = `${index}:${group.label ?? ''}`\n\n return {\n key,\n label: group.label ?? null,\n icon: group.icon ?? undefined,\n items: group.items.map((item, itemIndex) => toNavItem(item, `${key}.${itemIndex}`)),\n }\n })\n}\n\n// ---------------------------------------------------------------- Browser runtime\n\n/**\n * What the browser-wide listeners of starter kit mode read: the open Alfakit page's panel\n * and error notifications, or nothing while a page of the host application is open (its\n * errors keep Inertia's default handling).\n */\nconst runtime: {\n panel: PanelSchema | null\n errorNotifications: ErrorNotificationsSchema | false | undefined\n installed: boolean\n} = { panel: null, errorNotifications: undefined, installed: false }\n\n/**\n * Record the Alfakit page being rendered (called by each renderer's starter kit root while\n * it renders); `null` once the root unmounts, when a host page opens.\n */\nexport function syncStarterKitPage(props: Partial<AlfakitPageProps> | null): void {\n const panel = props?.alfakit ?? null\n\n runtime.panel = panel\n runtime.errorNotifications = panel ? effectiveErrorNotifications(panel, props?.page) : undefined\n\n if (typeof window !== 'undefined') {\n // Internal requests and form stores are recorded only while the page carries the debug prop.\n debugRecorder.setEnabled(props?.alfakitDebug !== undefined)\n }\n}\n\n/** The panel of the open Alfakit page in starter kit mode, or null on host pages. */\nexport function currentStarterKitPanel(): PanelSchema | null {\n return runtime.panel\n}\n\n/**\n * The listeners `createAlfakit()` installs, once per page load, for starter kit mode: reload\n * on an expired CSRF token (419), the panel's error notifications instead of Inertia's error\n * modal, a notification for failed internal requests and the panel's SPA URL exceptions.\n * Returns false when they were already installed (or on the server).\n */\nexport function installStarterKitRuntime(\n show: (notification: NotificationSchema) => void,\n t: (key: string, replacements?: Record<string, string | number>, fallback?: string) => string,\n): boolean {\n if (typeof window === 'undefined' || runtime.installed) return false\n\n runtime.installed = true\n\n reloadOnExpiredPage()\n installSpaUrlExceptions(() => runtime.panel)\n installErrorNotifications(() => ({ errorNotifications: runtime.errorNotifications }), show)\n setRequestErrorReporter((error) => {\n const notification = resolveRequestErrorNotification(error, runtime.errorNotifications, t)\n\n if (notification) show(notification)\n })\n\n return true\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiCA,MAAa,yBAAyB;;AAGtC,SAAgB,kBACd,OACS;CACT,OAAO,OAAO,eAAe;AAC/B;;;;;;;AAcA,SAAgB,wBACd,aACwB;CACxB,MAAM,OAAO,eAAe,CAAC;CAC7B,MAAM,uBAAO,IAAI,IAAY;CAE7B,OAAO,KAAK,KAAK,OAAO,UAAU;EAChC,IAAI,OAAO,MAAM,QAAQ,UAAU,KAAK,SAAS,IAAI,KAAK,IAAI;EAE9D,IAAI,KAAK,IAAI,IAAI,GAAG,OAAO,GAAG,KAAK,GAAG;EAEtC,KAAK,IAAI,IAAI;EAEb,OAAO;GAAE,OAAO,MAAM;GAAO;EAAK;CACpC,CAAC;AACH;;AAGA,SAAgB,+BAA+B,OAAwC;CACrF,MAAM,OAAQ,OAA8E;CAE5F,OAAO,wBAAwB,MAAM,WAAW;AAClD;;;;;AAMA,SAAgB,sBAAsB,OAA8C;CAClF,MAAM,QAAS,OAA8D;CAE7E,OAAO,MAAM,QAAQ,KAAK,IAAK,QAAyC,CAAC;AAC3E;;AAGA,SAAgB,qBACd,OACA,SACmC;CACnC,MAAM,cAAc,sBAAsB,KAAK;CAE/C,QACG,YAAY,KAAA,IACT,YAAY,KACZ,YAAY,MAAM,eAAe,WAAW,OAAO,OAAO,MAAM;AAExE;AA0BA,SAAS,UAAU,MAA4B,KAAgC;CAC7E,OAAO;EACL;EACA,OAAO,mBAAmB,IAAI;EAC9B,MAAM,KAAK,OAAO;EAClB,MAAM,KAAK,QAAQ,KAAA;EACnB,UAAU,KAAK,WAAW;EAC1B,cAAc,KAAK,iBAAiB;EACpC,OAAO,KAAK,SAAS,KAAA;EACrB,YAAY,KAAK,cAAc,KAAA;EAC/B,cAAc,KAAK,gBAAgB,KAAA;EACnC,WAAW,KAAK,YAAY,CAAC,EAAA,CAAG,KAAK,OAAO,UAAU,UAAU,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC;CAC3F;AACF;;AAGA,SAAgB,sBACd,QACsB;CACtB,QAAQ,UAAU,CAAC,EAAA,CAAG,KAAK,OAAO,UAAU;EAC1C,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,SAAS;EAEvC,OAAO;GACL;GACA,OAAO,MAAM,SAAS;GACtB,MAAM,MAAM,QAAQ,KAAA;GACpB,OAAO,MAAM,MAAM,KAAK,MAAM,cAAc,UAAU,MAAM,GAAG,IAAI,GAAG,WAAW,CAAC;EACpF;CACF,CAAC;AACH;;;;;;AASA,MAAM,UAIF;CAAE,OAAO;CAAM,oBAAoB,KAAA;CAAW,WAAW;AAAM;;;;;AAMnE,SAAgB,mBAAmB,OAA+C;CAChF,MAAM,QAAQ,OAAO,WAAW;CAEhC,QAAQ,QAAQ;CAChB,QAAQ,qBAAqB,QAAQ,4BAA4B,OAAO,OAAO,IAAI,IAAI,KAAA;CAEvF,IAAI,OAAO,WAAW,aAEpB,cAAc,WAAW,OAAO,iBAAiB,KAAA,CAAS;AAE9D;;AAGA,SAAgB,yBAA6C;CAC3D,OAAO,QAAQ;AACjB;;;;;;;AAQA,SAAgB,yBACd,MACA,GACS;CACT,IAAI,OAAO,WAAW,eAAe,QAAQ,WAAW,OAAO;CAE/D,QAAQ,YAAY;CAEpB,oBAAoB;CACpB,8BAA8B,QAAQ,KAAK;CAC3C,iCAAiC,EAAE,oBAAoB,QAAQ,mBAAmB,IAAI,IAAI;CAC1F,yBAAyB,UAAU;EACjC,MAAM,eAAe,gCAAgC,OAAO,QAAQ,oBAAoB,CAAC;EAEzF,IAAI,cAAc,KAAK,YAAY;CACrC,CAAC;CAED,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"starter-kit.js","names":[],"sources":["../src/starter-kit.ts"],"sourcesContent":["import { debugRecorder } from './debug'\nimport {\n effectiveErrorNotifications,\n installErrorNotifications,\n resolveRequestErrorNotification,\n setRequestErrorReporter,\n} from './error-notifications'\nimport { reloadOnExpiredPage } from './http'\nimport { navigationItemText } from './navigation'\nimport type { NotificationSchema } from './schema/notifications'\nimport type {\n AlfakitPageProps,\n BreadcrumbSchema,\n ErrorNotificationsSchema,\n NavigationGroupSchema,\n NavigationItemSchema,\n PanelSchema,\n StarterKitNavigationSchema,\n} from './schema/panel'\nimport { installSpaUrlExceptions } from './spa'\n\n/**\n * Starter kit mode (`Panel::starterKit()`): Alfakit pages render inside an application made\n * from Laravel's React, Vue or Svelte starter kit, in the host's own layout. These helpers are\n * shared by the three renderers; the host's sidebar reads the navigation through each\n * renderer's `useAlfakitNavigation()`.\n */\n\n/**\n * The sonner toaster Alfakit renders in starter kit mode. The host layout mounts its own\n * id-less `<Toaster />`; giving Alfakit's an id keeps each toast in one toaster even when the\n * host and Alfakit resolve the same sonner instance.\n */\nexport const STARTER_KIT_TOASTER_ID = 'alfakit'\n\n/** Whether the panel runs inside a starter kit application (`Panel::starterKit()`). */\nexport function isStarterKitPanel(\n panel: Pick<PanelSchema, 'starterKit'> | null | undefined,\n): boolean {\n return panel?.starterKit === true\n}\n\n/** A breadcrumb as the starter kits' `AppLayout` takes it (`BreadcrumbItem`). */\nexport interface StarterKitBreadcrumb {\n title: string\n href: string\n}\n\n/**\n * The page's breadcrumbs in the starter kits' shape: `{ title, href }` instead of\n * `{ label, url }`. The kits render the last crumb (the current page) as plain text and key\n * the list by `href`, so every `href` is unique: the last crumb without a URL keeps an empty\n * one, other crumbs without one (or repeating one) get a `#index` fragment.\n */\nexport function toStarterKitBreadcrumbs(\n breadcrumbs: BreadcrumbSchema[] | null | undefined,\n): StarterKitBreadcrumb[] {\n const list = breadcrumbs ?? []\n const seen = new Set<string>()\n\n return list.map((crumb, index) => {\n let href = crumb.url ?? (index === list.length - 1 ? '' : `#${index}`)\n\n if (seen.has(href)) href = `${href}#${index}`\n\n seen.add(href)\n\n return { title: crumb.label, href }\n })\n}\n\n/** The breadcrumbs of an Alfakit page from its Inertia props (`props.page.breadcrumbs`). */\n/**\n * Whether an Alfakit page renders inside the host layout (`createStarterKitPage({ layout })`).\n * Pages with the `auth` layout (sign-in, registration, password reset, multi-factor\n * challenge, email verification, `->login()` brought back after `starterKit()`) stand on\n * their own, like the host's auth pages: the host layout expects a signed-in user.\n */\nexport function usesStarterKitHostLayout(props: unknown): boolean {\n const page = (props as { page?: { layout?: string } } | null | undefined)?.page\n\n return page?.layout !== 'auth'\n}\n\nexport function starterKitBreadcrumbsFromProps(props: unknown): StarterKitBreadcrumb[] {\n const page = (props as { page?: { breadcrumbs?: BreadcrumbSchema[] } } | null | undefined)?.page\n\n return toStarterKitBreadcrumbs(page?.breadcrumbs)\n}\n\n/**\n * The shared `alfakitNavigation` prop of a page: one entry per `starterKit()` panel, or none\n * for guests and pages of other panels.\n */\nexport function starterKitNavigations(props: unknown): StarterKitNavigationSchema[] {\n const value = (props as { alfakitNavigation?: unknown } | null | undefined)?.alfakitNavigation\n\n return Array.isArray(value) ? (value as StarterKitNavigationSchema[]) : []\n}\n\n/**\n * The panel of the open AlfaKit page (`props.alfakit.id`), or undefined on the host's own\n * pages. With several `starterKit()` panels, components without a `panel` follow it.\n */\nexport function currentStarterKitPanelId(props: unknown): string | undefined {\n const id = (props as { alfakit?: { id?: unknown } } | null | undefined)?.alfakit?.id\n\n return typeof id === 'string' ? id : undefined\n}\n\n/**\n * Order panel entries for components without a `panel` id: the open AlfaKit page's panel\n * first (an `/app` page of a second `starterKit()` panel shows that panel's navigation and\n * tenant menu), then the others in registration order.\n */\nexport function preferCurrentStarterKitPanel<T extends { id: string }>(\n entries: T[],\n props: unknown,\n): T[] {\n const current = currentStarterKitPanelId(props)\n const index = current === undefined ? -1 : entries.findIndex((entry) => entry.id === current)\n\n return index <= 0 ? entries : [entries[index]!, ...entries.filter((_, i) => i !== index)]\n}\n\n/**\n * One panel's navigation, or null. Without an id: the open AlfaKit page's panel, else the\n * first starter kit panel.\n */\nexport function starterKitNavigation(\n props: unknown,\n panelId?: string,\n): StarterKitNavigationSchema | null {\n const navigations = starterKitNavigations(props)\n\n return (\n (panelId === undefined\n ? preferCurrentStarterKitPanel(navigations, props)[0]\n : navigations.find((navigation) => navigation.id === panelId)) ?? null\n )\n}\n\n/**\n * A navigation item flattened for a starter kit sidebar: the label as text and the item's\n * nested children. `title`/`href` match the kits' `NavItem` so the host can reuse its types.\n */\nexport interface StarterKitNavItem {\n key: string\n title: string\n href: string\n icon?: string\n isActive: boolean\n openInNewTab: boolean\n badge?: string | number\n badgeColor?: string\n badgeTooltip?: string\n children: StarterKitNavItem[]\n}\n\nexport interface StarterKitNavGroup {\n key: string\n label: string | null\n icon?: string\n items: StarterKitNavItem[]\n}\n\nfunction toNavItem(item: NavigationItemSchema, key: string): StarterKitNavItem {\n return {\n key,\n title: navigationItemText(item),\n href: item.url ?? '',\n icon: item.icon ?? undefined,\n isActive: item.active === true,\n openInNewTab: item.openInNewTab === true,\n badge: item.badge ?? undefined,\n badgeColor: item.badgeColor ?? undefined,\n badgeTooltip: item.badgeTooltip ?? undefined,\n children: (item.children ?? []).map((child, index) => toNavItem(child, `${key}.${index}`)),\n }\n}\n\n/** A panel's navigation groups as plain items for the host's sidebar primitives. */\nexport function toStarterKitNavGroups(\n groups: NavigationGroupSchema[] | null | undefined,\n): StarterKitNavGroup[] {\n return (groups ?? []).map((group, index) => {\n const key = `${index}:${group.label ?? ''}`\n\n return {\n key,\n label: group.label ?? null,\n icon: group.icon ?? undefined,\n items: group.items.map((item, itemIndex) => toNavItem(item, `${key}.${itemIndex}`)),\n }\n })\n}\n\n// ---------------------------------------------------------------- Browser runtime\n\n/**\n * What the browser-wide listeners of starter kit mode read: the open Alfakit page's panel\n * and error notifications, or nothing while a page of the host application is open (its\n * errors keep Inertia's default handling).\n */\nconst runtime: {\n panel: PanelSchema | null\n errorNotifications: ErrorNotificationsSchema | false | undefined\n installed: boolean\n} = { panel: null, errorNotifications: undefined, installed: false }\n\n/**\n * Record the Alfakit page being rendered (called by each renderer's starter kit root while\n * it renders); `null` once the root unmounts, when a host page opens.\n */\nexport function syncStarterKitPage(props: Partial<AlfakitPageProps> | null): void {\n const panel = props?.alfakit ?? null\n\n runtime.panel = panel\n runtime.errorNotifications = panel ? effectiveErrorNotifications(panel, props?.page) : undefined\n\n if (typeof window !== 'undefined') {\n // Internal requests and form stores are recorded only while the page carries the debug prop.\n debugRecorder.setEnabled(props?.alfakitDebug !== undefined)\n }\n}\n\n/** The panel of the open Alfakit page in starter kit mode, or null on host pages. */\nexport function currentStarterKitPanel(): PanelSchema | null {\n return runtime.panel\n}\n\n/**\n * The listeners `createAlfakit()` installs, once per page load, for starter kit mode: reload\n * on an expired CSRF token (419), the panel's error notifications instead of Inertia's error\n * modal, a notification for failed internal requests and the panel's SPA URL exceptions.\n * Returns false when they were already installed (or on the server).\n */\nexport function installStarterKitRuntime(\n show: (notification: NotificationSchema) => void,\n t: (key: string, replacements?: Record<string, string | number>, fallback?: string) => string,\n): boolean {\n if (typeof window === 'undefined' || runtime.installed) return false\n\n runtime.installed = true\n\n reloadOnExpiredPage()\n installSpaUrlExceptions(() => runtime.panel)\n installErrorNotifications(() => ({ errorNotifications: runtime.errorNotifications }), show)\n setRequestErrorReporter((error) => {\n const notification = resolveRequestErrorNotification(error, runtime.errorNotifications, t)\n\n if (notification) show(notification)\n })\n\n return true\n}\n"],"mappings":"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"}
|
package/dist/utils/debounce.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export interface Debounced<TArgs extends unknown[]> {
|
|
|
3
3
|
(...args: TArgs): void;
|
|
4
4
|
cancel: () => void;
|
|
5
5
|
flush: () => void;
|
|
6
|
+
/** A call is waiting for its timer. */
|
|
7
|
+
readonly pending: boolean;
|
|
6
8
|
}
|
|
7
9
|
export declare function debounce<TArgs extends unknown[]>(callback: (...args: TArgs) => void, wait: number): Debounced<TArgs>;
|
|
8
10
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debounce.d.ts","names":[],"sources":["../../src/utils/debounce.ts"],"mappings":";iBAAiB,UAAU;MACrB,MAAM;EACV;EACA;;
|
|
1
|
+
{"version":3,"file":"debounce.d.ts","names":[],"sources":["../../src/utils/debounce.ts"],"mappings":";iBAAiB,UAAU;MACrB,MAAM;EACV;EACA;;WAES;;wBAGK,SAAS,yBACvB,cAAc,MAAM,gBACpB,eACC,UAAU"}
|
package/dist/utils/debounce.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debounce.js","names":[],"sources":["../../src/utils/debounce.ts"],"sourcesContent":["export interface Debounced<TArgs extends unknown[]> {\n (...args: TArgs): void\n cancel: () => void\n flush: () => void\n}\n\nexport function debounce<TArgs extends unknown[]>(\n callback: (...args: TArgs) => void,\n wait: number,\n): Debounced<TArgs> {\n let timer: ReturnType<typeof setTimeout> | null = null\n let pending: TArgs | null = null\n\n const debounced = ((...args: TArgs) => {\n pending = args\n\n if (timer !== null) {\n clearTimeout(timer)\n }\n\n timer = setTimeout(() => {\n timer = null\n const current = pending\n pending = null\n\n if (current) {\n callback(...current)\n }\n }, wait)\n }) as Debounced<TArgs>\n\n debounced.cancel = () => {\n if (timer !== null) {\n clearTimeout(timer)\n timer = null\n }\n\n pending = null\n }\n\n debounced.flush = () => {\n if (timer !== null && pending) {\n clearTimeout(timer)\n timer = null\n const current = pending\n pending = null\n callback(...current)\n }\n }\n\n return debounced\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"debounce.js","names":[],"sources":["../../src/utils/debounce.ts"],"sourcesContent":["export interface Debounced<TArgs extends unknown[]> {\n (...args: TArgs): void\n cancel: () => void\n flush: () => void\n /** A call is waiting for its timer. */\n readonly pending: boolean\n}\n\nexport function debounce<TArgs extends unknown[]>(\n callback: (...args: TArgs) => void,\n wait: number,\n): Debounced<TArgs> {\n let timer: ReturnType<typeof setTimeout> | null = null\n let pending: TArgs | null = null\n\n const debounced = ((...args: TArgs) => {\n pending = args\n\n if (timer !== null) {\n clearTimeout(timer)\n }\n\n timer = setTimeout(() => {\n timer = null\n const current = pending\n pending = null\n\n if (current) {\n callback(...current)\n }\n }, wait)\n }) as Debounced<TArgs>\n\n debounced.cancel = () => {\n if (timer !== null) {\n clearTimeout(timer)\n timer = null\n }\n\n pending = null\n }\n\n Object.defineProperty(debounced, 'pending', { get: () => timer !== null && pending !== null })\n\n debounced.flush = () => {\n if (timer !== null && pending) {\n clearTimeout(timer)\n timer = null\n const current = pending\n pending = null\n callback(...current)\n }\n }\n\n return debounced\n}\n"],"mappings":";AAQA,SAAgB,SACd,UACA,MACkB;CAClB,IAAI,QAA8C;CAClD,IAAI,UAAwB;CAE5B,MAAM,cAAc,GAAG,SAAgB;EACrC,UAAU;EAEV,IAAI,UAAU,MACZ,aAAa,KAAK;EAGpB,QAAQ,iBAAiB;GACvB,QAAQ;GACR,MAAM,UAAU;GAChB,UAAU;GAEV,IAAI,SACF,SAAS,GAAG,OAAO;EAEvB,GAAG,IAAI;CACT;CAEA,UAAU,eAAe;EACvB,IAAI,UAAU,MAAM;GAClB,aAAa,KAAK;GAClB,QAAQ;EACV;EAEA,UAAU;CACZ;CAEA,OAAO,eAAe,WAAW,WAAW,EAAE,WAAW,UAAU,QAAQ,YAAY,KAAK,CAAC;CAE7F,UAAU,cAAc;EACtB,IAAI,UAAU,QAAQ,SAAS;GAC7B,aAAa,KAAK;GAClB,QAAQ;GACR,MAAM,UAAU;GAChB,UAAU;GACV,SAAS,GAAG,OAAO;EACrB;CACF;CAEA,OAAO;AACT"}
|
package/dist/utils/path.d.ts
CHANGED
|
@@ -17,8 +17,18 @@ export declare function parentPath(path: string): string;
|
|
|
17
17
|
export declare function joinPath(...segments: PathSegment[]): string;
|
|
18
18
|
/**
|
|
19
19
|
* Replace the Repeater template placeholder with a concrete index, deeply, in any
|
|
20
|
-
* string value of the object (state paths, keys, ids).
|
|
20
|
+
* string value of the object (state paths, keys, ids). Only the first placeholder of each
|
|
21
|
+
* string is this level's: a repeater inside a builder block template has item paths like
|
|
22
|
+
* `content.__INDEX__.data.items.__INDEX__.question`, whose second placeholder is filled
|
|
23
|
+
* in when an item is added to that repeater.
|
|
21
24
|
*/
|
|
22
25
|
export declare function replacePlaceholder<T>(value: T, placeholder: string, replacement: string): T;
|
|
26
|
+
/**
|
|
27
|
+
* A Repeater or Builder template with the item index filled in (`replacePlaceholder()`),
|
|
28
|
+
* the same object for the same template and index. Items the server hasn't seen yet render
|
|
29
|
+
* from their template on every render: new objects each time made every field below them
|
|
30
|
+
* render again (and restart work such as the image editor's loading).
|
|
31
|
+
*/
|
|
32
|
+
export declare function templateForIndex<T extends object>(template: T, index: number | string): T;
|
|
23
33
|
//#endregion
|
|
24
34
|
//# sourceMappingURL=path.d.ts.map
|
package/dist/utils/path.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.d.ts","names":[],"sources":["../../src/utils/path.ts"],"mappings":";;;;;YAKY;wBAEI,UAAU;wBAIV,QAAQ,aAAa,iBAAiB,cAAc,WAAW,IAAI;wBAkBnE,QAAQ,iBAAiB;;;;;wBAuBzB,QAAQ,kBAAkB,QAAQ,GAAG,cAAc,iBAAiB;wBAqCpE,WAAW,kBAAkB,QAAQ,GAAG,eAAe;wBA4BvD,WAAW;wBAOX,YAAY,UAAU
|
|
1
|
+
{"version":3,"file":"path.d.ts","names":[],"sources":["../../src/utils/path.ts"],"mappings":";;;;;YAKY;wBAEI,UAAU;wBAIV,QAAQ,aAAa,iBAAiB,cAAc,WAAW,IAAI;wBAkBnE,QAAQ,iBAAiB;;;;;wBAuBzB,QAAQ,kBAAkB,QAAQ,GAAG,cAAc,iBAAiB;wBAqCpE,WAAW,kBAAkB,QAAQ,GAAG,eAAe;wBA4BvD,WAAW;wBAOX,YAAY,UAAU;;;;;;;;wBActB,mBAAmB,GAAG,OAAO,GAAG,qBAAqB,sBAAsB;;;;;;;wBAoC3E,iBAAiB,kBAAkB,UAAU,GAAG,yBAAyB"}
|
package/dist/utils/path.js
CHANGED
|
@@ -67,10 +67,16 @@ function joinPath(...segments) {
|
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Replace the Repeater template placeholder with a concrete index, deeply, in any
|
|
70
|
-
* string value of the object (state paths, keys, ids).
|
|
70
|
+
* string value of the object (state paths, keys, ids). Only the first placeholder of each
|
|
71
|
+
* string is this level's: a repeater inside a builder block template has item paths like
|
|
72
|
+
* `content.__INDEX__.data.items.__INDEX__.question`, whose second placeholder is filled
|
|
73
|
+
* in when an item is added to that repeater.
|
|
71
74
|
*/
|
|
72
75
|
function replacePlaceholder(value, placeholder, replacement) {
|
|
73
|
-
if (typeof value === "string")
|
|
76
|
+
if (typeof value === "string") {
|
|
77
|
+
const at = value.indexOf(placeholder);
|
|
78
|
+
return at === -1 ? value : value.slice(0, at) + replacement + value.slice(at + placeholder.length);
|
|
79
|
+
}
|
|
74
80
|
if (Array.isArray(value)) return value.map((item) => replacePlaceholder(item, placeholder, replacement));
|
|
75
81
|
if (value !== null && typeof value === "object") {
|
|
76
82
|
const result = {};
|
|
@@ -79,7 +85,28 @@ function replacePlaceholder(value, placeholder, replacement) {
|
|
|
79
85
|
}
|
|
80
86
|
return value;
|
|
81
87
|
}
|
|
88
|
+
const templateInstances = /* @__PURE__ */ new WeakMap();
|
|
89
|
+
/**
|
|
90
|
+
* A Repeater or Builder template with the item index filled in (`replacePlaceholder()`),
|
|
91
|
+
* the same object for the same template and index. Items the server hasn't seen yet render
|
|
92
|
+
* from their template on every render: new objects each time made every field below them
|
|
93
|
+
* render again (and restart work such as the image editor's loading).
|
|
94
|
+
*/
|
|
95
|
+
function templateForIndex(template, index) {
|
|
96
|
+
let instances = templateInstances.get(template);
|
|
97
|
+
if (!instances) {
|
|
98
|
+
instances = /* @__PURE__ */ new Map();
|
|
99
|
+
templateInstances.set(template, instances);
|
|
100
|
+
}
|
|
101
|
+
const key = String(index);
|
|
102
|
+
let instance = instances.get(key);
|
|
103
|
+
if (instance === void 0) {
|
|
104
|
+
instance = replacePlaceholder(template, "__INDEX__", key);
|
|
105
|
+
instances.set(key, instance);
|
|
106
|
+
}
|
|
107
|
+
return instance;
|
|
108
|
+
}
|
|
82
109
|
//#endregion
|
|
83
|
-
export { deletePath, getPath, hasPath, joinPath, parentPath, replacePlaceholder, setPath, splitPath };
|
|
110
|
+
export { deletePath, getPath, hasPath, joinPath, parentPath, replacePlaceholder, setPath, splitPath, templateForIndex };
|
|
84
111
|
|
|
85
112
|
//# sourceMappingURL=path.js.map
|
package/dist/utils/path.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.js","names":[],"sources":["../../src/utils/path.ts"],"sourcesContent":["/**\n * Dot-path helpers mirroring Laravel's `data_get` / `data_set` semantics, used for form\n * state addressed by `statePath` (e.g. `comments.0.body`).\n */\n\nexport type PathSegment = string | number\n\nexport function splitPath(path: string): string[] {\n return path === '' ? [] : path.split('.')\n}\n\nexport function getPath<T = unknown>(source: unknown, path: string, fallback?: T): T {\n if (path === '') {\n return source as T\n }\n\n let current: unknown = source\n\n for (const segment of splitPath(path)) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return fallback as T\n }\n\n current = (current as Record<string, unknown>)[segment]\n }\n\n return (current === undefined ? fallback : current) as T\n}\n\nexport function hasPath(source: unknown, path: string): boolean {\n let current: unknown = source\n\n for (const segment of splitPath(path)) {\n if (\n current === null ||\n current === undefined ||\n typeof current !== 'object' ||\n !(segment in (current as object))\n ) {\n return false\n }\n\n current = (current as Record<string, unknown>)[segment]\n }\n\n return true\n}\n\n/**\n * Immutably set a value, cloning each container along the path. Numeric segments on a\n * missing container create arrays.\n */\nexport function setPath<T extends object>(source: T, path: string, value: unknown): T {\n const segments = splitPath(path)\n\n if (segments.length === 0) {\n return value as T\n }\n\n const root: unknown = Array.isArray(source) ? [...source] : { ...(source ?? {}) }\n let current = root as Record<string, unknown>\n\n segments.forEach((segment, index) => {\n const isLast = index === segments.length - 1\n\n if (isLast) {\n current[segment] = value\n\n return\n }\n\n const existing = current[segment]\n const nextSegment = segments[index + 1] ?? ''\n const container =\n existing !== null && typeof existing === 'object'\n ? Array.isArray(existing)\n ? [...existing]\n : { ...existing }\n : /^\\d+$/.test(nextSegment)\n ? []\n : {}\n\n current[segment] = container\n current = container as Record<string, unknown>\n })\n\n return root as T\n}\n\nexport function deletePath<T extends object>(source: T, path: string): T {\n const segments = splitPath(path)\n const last = segments.pop()\n\n if (last === undefined) {\n return source\n }\n\n const parentPath = segments.join('.')\n const parent = getPath<Record<string, unknown> | unknown[]>(source, parentPath)\n\n if (parent === null || parent === undefined || typeof parent !== 'object') {\n return source\n }\n\n if (Array.isArray(parent)) {\n const copy = [...parent]\n copy.splice(Number(last), 1)\n\n return setPath(source, parentPath, copy)\n }\n\n const copy = { ...parent }\n delete copy[last]\n\n return setPath(source, parentPath, copy)\n}\n\nexport function parentPath(path: string): string {\n const segments = splitPath(path)\n segments.pop()\n\n return segments.join('.')\n}\n\nexport function joinPath(...segments: PathSegment[]): string {\n return segments\n .map(String)\n .filter((segment) => segment !== '')\n .join('.')\n}\n\n/**\n * Replace the Repeater template placeholder with a concrete index, deeply, in any\n * string value of the object (state paths, keys, ids).\n */\nexport function replacePlaceholder<T>(value: T, placeholder: string, replacement: string): T {\n if (typeof value === 'string') {\n
|
|
1
|
+
{"version":3,"file":"path.js","names":[],"sources":["../../src/utils/path.ts"],"sourcesContent":["/**\n * Dot-path helpers mirroring Laravel's `data_get` / `data_set` semantics, used for form\n * state addressed by `statePath` (e.g. `comments.0.body`).\n */\n\nexport type PathSegment = string | number\n\nexport function splitPath(path: string): string[] {\n return path === '' ? [] : path.split('.')\n}\n\nexport function getPath<T = unknown>(source: unknown, path: string, fallback?: T): T {\n if (path === '') {\n return source as T\n }\n\n let current: unknown = source\n\n for (const segment of splitPath(path)) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return fallback as T\n }\n\n current = (current as Record<string, unknown>)[segment]\n }\n\n return (current === undefined ? fallback : current) as T\n}\n\nexport function hasPath(source: unknown, path: string): boolean {\n let current: unknown = source\n\n for (const segment of splitPath(path)) {\n if (\n current === null ||\n current === undefined ||\n typeof current !== 'object' ||\n !(segment in (current as object))\n ) {\n return false\n }\n\n current = (current as Record<string, unknown>)[segment]\n }\n\n return true\n}\n\n/**\n * Immutably set a value, cloning each container along the path. Numeric segments on a\n * missing container create arrays.\n */\nexport function setPath<T extends object>(source: T, path: string, value: unknown): T {\n const segments = splitPath(path)\n\n if (segments.length === 0) {\n return value as T\n }\n\n const root: unknown = Array.isArray(source) ? [...source] : { ...(source ?? {}) }\n let current = root as Record<string, unknown>\n\n segments.forEach((segment, index) => {\n const isLast = index === segments.length - 1\n\n if (isLast) {\n current[segment] = value\n\n return\n }\n\n const existing = current[segment]\n const nextSegment = segments[index + 1] ?? ''\n const container =\n existing !== null && typeof existing === 'object'\n ? Array.isArray(existing)\n ? [...existing]\n : { ...existing }\n : /^\\d+$/.test(nextSegment)\n ? []\n : {}\n\n current[segment] = container\n current = container as Record<string, unknown>\n })\n\n return root as T\n}\n\nexport function deletePath<T extends object>(source: T, path: string): T {\n const segments = splitPath(path)\n const last = segments.pop()\n\n if (last === undefined) {\n return source\n }\n\n const parentPath = segments.join('.')\n const parent = getPath<Record<string, unknown> | unknown[]>(source, parentPath)\n\n if (parent === null || parent === undefined || typeof parent !== 'object') {\n return source\n }\n\n if (Array.isArray(parent)) {\n const copy = [...parent]\n copy.splice(Number(last), 1)\n\n return setPath(source, parentPath, copy)\n }\n\n const copy = { ...parent }\n delete copy[last]\n\n return setPath(source, parentPath, copy)\n}\n\nexport function parentPath(path: string): string {\n const segments = splitPath(path)\n segments.pop()\n\n return segments.join('.')\n}\n\nexport function joinPath(...segments: PathSegment[]): string {\n return segments\n .map(String)\n .filter((segment) => segment !== '')\n .join('.')\n}\n\n/**\n * Replace the Repeater template placeholder with a concrete index, deeply, in any\n * string value of the object (state paths, keys, ids). Only the first placeholder of each\n * string is this level's: a repeater inside a builder block template has item paths like\n * `content.__INDEX__.data.items.__INDEX__.question`, whose second placeholder is filled\n * in when an item is added to that repeater.\n */\nexport function replacePlaceholder<T>(value: T, placeholder: string, replacement: string): T {\n if (typeof value === 'string') {\n const at = value.indexOf(placeholder)\n\n return (\n at === -1 ? value : value.slice(0, at) + replacement + value.slice(at + placeholder.length)\n ) as T\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => replacePlaceholder(item, placeholder, replacement)) as T\n }\n\n if (value !== null && typeof value === 'object') {\n const result: Record<string, unknown> = {}\n\n for (const [key, nested] of Object.entries(value as Record<string, unknown>)) {\n result[key] = replacePlaceholder(nested, placeholder, replacement)\n }\n\n return result as T\n }\n\n return value\n}\n\n// Instances of a template per index, kept while the template object lives (it is replaced\n// when the server sends a new schema).\nconst templateInstances = new WeakMap<object, Map<string, unknown>>()\n\n/**\n * A Repeater or Builder template with the item index filled in (`replacePlaceholder()`),\n * the same object for the same template and index. Items the server hasn't seen yet render\n * from their template on every render: new objects each time made every field below them\n * render again (and restart work such as the image editor's loading).\n */\nexport function templateForIndex<T extends object>(template: T, index: number | string): T {\n let instances = templateInstances.get(template)\n\n if (!instances) {\n instances = new Map()\n templateInstances.set(template, instances)\n }\n\n const key = String(index)\n let instance = instances.get(key) as T | undefined\n\n if (instance === undefined) {\n instance = replacePlaceholder(template, '__INDEX__', key)\n instances.set(key, instance)\n }\n\n return instance\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfakit/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Framework-agnostic schema types and state management for Alfakit, the Laravel admin panel builder by Alfa Six.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Alfa Six (https://alfasixbh.com)",
|
package/themes.css
CHANGED
|
@@ -287,7 +287,7 @@
|
|
|
287
287
|
--secondary: oklch(0.967 0.003 264.542);
|
|
288
288
|
--secondary-foreground: oklch(0.21 0.034 264.665);
|
|
289
289
|
--muted: oklch(0.967 0.003 264.542);
|
|
290
|
-
--muted-foreground: oklch(0.
|
|
290
|
+
--muted-foreground: oklch(0.535 0.027 264.364);
|
|
291
291
|
--accent: oklch(0.967 0.003 264.542);
|
|
292
292
|
--accent-foreground: oklch(0.21 0.034 264.665);
|
|
293
293
|
--border: oklch(0.928 0.006 264.531);
|
|
@@ -678,6 +678,11 @@
|
|
|
678
678
|
color: var(--primary);
|
|
679
679
|
}
|
|
680
680
|
|
|
681
|
+
/* The schema inspector's round button (dev tools) sits above the bar, not on its last item. */
|
|
682
|
+
:root[data-mobile='bottom'] [data-slot='dev-tools-toggle'] {
|
|
683
|
+
bottom: calc(var(--alfakit-bottom-nav-height) + env(safe-area-inset-bottom, 0px) + 1rem);
|
|
684
|
+
}
|
|
685
|
+
|
|
681
686
|
/* Room for the bar, sticky actions sit right above it. */
|
|
682
687
|
:root[data-mobile='bottom'] [data-slot='content'] {
|
|
683
688
|
padding-bottom: calc(
|