@pilotiq/pilotiq 0.6.1 → 0.7.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/.turbo/turbo-build.log +6 -2
- package/CHANGELOG.md +614 -0
- package/CLAUDE.md +6 -5
- package/dist/Column.d.ts +35 -0
- package/dist/Column.d.ts.map +1 -1
- package/dist/Column.js +41 -0
- package/dist/Column.js.map +1 -1
- package/dist/Page.d.ts +13 -4
- package/dist/Page.d.ts.map +1 -1
- package/dist/Page.js +9 -2
- package/dist/Page.js.map +1 -1
- package/dist/Pilotiq.d.ts +84 -0
- package/dist/Pilotiq.d.ts.map +1 -1
- package/dist/Pilotiq.js +66 -0
- package/dist/Pilotiq.js.map +1 -1
- package/dist/Resource.d.ts +26 -0
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +9 -0
- package/dist/Resource.js.map +1 -1
- package/dist/actions/exportFactory.js +1 -1
- package/dist/actions/exportFactory.js.map +1 -1
- package/dist/columns/SelectColumn.d.ts +32 -5
- package/dist/columns/SelectColumn.d.ts.map +1 -1
- package/dist/columns/SelectColumn.js +37 -7
- package/dist/columns/SelectColumn.js.map +1 -1
- package/dist/defaultPages.d.ts.map +1 -1
- package/dist/defaultPages.js +3 -0
- package/dist/defaultPages.js.map +1 -1
- package/dist/elements/Form.d.ts +17 -0
- package/dist/elements/Form.d.ts.map +1 -1
- package/dist/elements/Form.js +17 -0
- package/dist/elements/Form.js.map +1 -1
- package/dist/elements/Table.d.ts +26 -0
- package/dist/elements/Table.d.ts.map +1 -1
- package/dist/elements/Table.js +15 -1
- package/dist/elements/Table.js.map +1 -1
- package/dist/elements/TableGroup.d.ts +84 -0
- package/dist/elements/TableGroup.d.ts.map +1 -1
- package/dist/elements/TableGroup.js +103 -0
- package/dist/elements/TableGroup.js.map +1 -1
- package/dist/elements/dispatchForm.d.ts.map +1 -1
- package/dist/elements/dispatchForm.js +36 -6
- package/dist/elements/dispatchForm.js.map +1 -1
- package/dist/elements/dispatchTable.d.ts +12 -0
- package/dist/elements/dispatchTable.d.ts.map +1 -1
- package/dist/elements/dispatchTable.js +104 -29
- package/dist/elements/dispatchTable.js.map +1 -1
- package/dist/fields/Field.d.ts +7 -2
- package/dist/fields/Field.d.ts.map +1 -1
- package/dist/fields/Field.js +8 -3
- package/dist/fields/Field.js.map +1 -1
- package/dist/fields/RepeaterField.d.ts +65 -0
- package/dist/fields/RepeaterField.d.ts.map +1 -1
- package/dist/fields/RepeaterField.js +48 -0
- package/dist/fields/RepeaterField.js.map +1 -1
- package/dist/orm/modelDefaults.d.ts.map +1 -1
- package/dist/orm/modelDefaults.js +19 -0
- package/dist/orm/modelDefaults.js.map +1 -1
- package/dist/pageData.d.ts +20 -0
- package/dist/pageData.d.ts.map +1 -1
- package/dist/pageData.js +242 -34
- package/dist/pageData.js.map +1 -1
- package/dist/react/AppShell.d.ts +17 -1
- package/dist/react/AppShell.d.ts.map +1 -1
- package/dist/react/AppShell.js +34 -3
- package/dist/react/AppShell.js.map +1 -1
- package/dist/react/PendingSuggestionApplierRegistry.d.ts +34 -0
- package/dist/react/PendingSuggestionApplierRegistry.d.ts.map +1 -0
- package/dist/react/PendingSuggestionApplierRegistry.js +51 -0
- package/dist/react/PendingSuggestionApplierRegistry.js.map +1 -0
- package/dist/react/PendingSuggestionOverlayRegistry.d.ts +46 -0
- package/dist/react/PendingSuggestionOverlayRegistry.d.ts.map +1 -0
- package/dist/react/PendingSuggestionOverlayRegistry.js +16 -0
- package/dist/react/PendingSuggestionOverlayRegistry.js.map +1 -0
- package/dist/react/PendingSuggestionsContext.d.ts +153 -0
- package/dist/react/PendingSuggestionsContext.d.ts.map +1 -0
- package/dist/react/PendingSuggestionsContext.js +46 -0
- package/dist/react/PendingSuggestionsContext.js.map +1 -0
- package/dist/react/SchemaRenderer.d.ts.map +1 -1
- package/dist/react/SchemaRenderer.js +312 -39
- package/dist/react/SchemaRenderer.js.map +1 -1
- package/dist/react/cells/EditableCell.d.ts +8 -0
- package/dist/react/cells/EditableCell.d.ts.map +1 -1
- package/dist/react/cells/EditableCell.js +6 -2
- package/dist/react/cells/EditableCell.js.map +1 -1
- package/dist/react/fields/CheckboxListInput.d.ts.map +1 -1
- package/dist/react/fields/CheckboxListInput.js +29 -2
- package/dist/react/fields/CheckboxListInput.js.map +1 -1
- package/dist/react/fields/ColorInput.d.ts.map +1 -1
- package/dist/react/fields/ColorInput.js +28 -2
- package/dist/react/fields/ColorInput.js.map +1 -1
- package/dist/react/fields/DateTimeInput.d.ts.map +1 -1
- package/dist/react/fields/DateTimeInput.js +28 -2
- package/dist/react/fields/DateTimeInput.js.map +1 -1
- package/dist/react/fields/FieldShell.d.ts.map +1 -1
- package/dist/react/fields/FieldShell.js +161 -3
- package/dist/react/fields/FieldShell.js.map +1 -1
- package/dist/react/fields/FileUploadInput.d.ts.map +1 -1
- package/dist/react/fields/FileUploadInput.js +27 -2
- package/dist/react/fields/FileUploadInput.js.map +1 -1
- package/dist/react/fields/KeyValueInput.d.ts.map +1 -1
- package/dist/react/fields/KeyValueInput.js +33 -2
- package/dist/react/fields/KeyValueInput.js.map +1 -1
- package/dist/react/fields/RadioInput.d.ts.map +1 -1
- package/dist/react/fields/RadioInput.js +28 -2
- package/dist/react/fields/RadioInput.js.map +1 -1
- package/dist/react/fields/SelectFieldInput.d.ts.map +1 -1
- package/dist/react/fields/SelectFieldInput.js +31 -2
- package/dist/react/fields/SelectFieldInput.js.map +1 -1
- package/dist/react/fields/SliderInput.d.ts.map +1 -1
- package/dist/react/fields/SliderInput.js +26 -2
- package/dist/react/fields/SliderInput.js.map +1 -1
- package/dist/react/fields/TagsInput.d.ts.map +1 -1
- package/dist/react/fields/TagsInput.js +26 -2
- package/dist/react/fields/TagsInput.js.map +1 -1
- package/dist/react/fields/ToggleFieldInput.d.ts.map +1 -1
- package/dist/react/fields/ToggleFieldInput.js +29 -2
- package/dist/react/fields/ToggleFieldInput.js.map +1 -1
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +3 -0
- package/dist/react/index.js.map +1 -1
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +55 -2
- package/dist/routes.js.map +1 -1
- package/dist/schema/Html.d.ts +2 -2
- package/dist/schema/Html.d.ts.map +1 -1
- package/dist/schema/Html.js +2 -2
- package/dist/schema/Html.js.map +1 -1
- package/dist/schema/Markdown.d.ts +2 -2
- package/dist/schema/Markdown.d.ts.map +1 -1
- package/dist/schema/Markdown.js +2 -2
- package/dist/schema/Markdown.js.map +1 -1
- package/dist/schema/Section.d.ts +16 -0
- package/dist/schema/Section.d.ts.map +1 -1
- package/dist/schema/Section.js +16 -0
- package/dist/schema/Section.js.map +1 -1
- package/dist/schema/Wizard.d.ts +45 -0
- package/dist/schema/Wizard.d.ts.map +1 -1
- package/dist/schema/Wizard.js +50 -0
- package/dist/schema/Wizard.js.map +1 -1
- package/dist/schema/resolveSchema.d.ts +8 -0
- package/dist/schema/resolveSchema.d.ts.map +1 -1
- package/dist/schema/resolveSchema.js +70 -1
- package/dist/schema/resolveSchema.js.map +1 -1
- package/dist/schema/sanitize.d.ts +3 -3
- package/dist/schema/sanitize.d.ts.map +1 -1
- package/dist/schema/sanitize.js +10 -3
- package/dist/schema/sanitize.js.map +1 -1
- package/dist/sessionFilters.d.ts.map +1 -1
- package/dist/sessionFilters.js +12 -1
- package/dist/sessionFilters.js.map +1 -1
- package/dist/styles/file-upload.css +13 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +9 -2
- package/dist/vite.js.map +1 -1
- package/package.json +6 -4
- package/src/Column.test.ts +36 -0
- package/src/Column.ts +54 -0
- package/src/Page.ts +13 -4
- package/src/Pilotiq.ts +109 -0
- package/src/Resource.ts +29 -0
- package/src/actions/exportFactory.ts +1 -1
- package/src/columns/SelectColumn.ts +46 -8
- package/src/columns/editableColumns.test.ts +45 -0
- package/src/defaultPages.ts +3 -0
- package/src/elements/Form.ts +19 -0
- package/src/elements/Table.ts +35 -1
- package/src/elements/TableGroup.test.ts +111 -0
- package/src/elements/TableGroup.ts +135 -0
- package/src/elements/dispatchForm.ts +34 -7
- package/src/elements/dispatchTable.test.ts +267 -0
- package/src/elements/dispatchTable.ts +112 -33
- package/src/fields/Field.test.ts +15 -0
- package/src/fields/Field.ts +8 -3
- package/src/fields/RepeaterField.ts +104 -0
- package/src/fields/RepeaterRelationship.test.ts +173 -0
- package/src/nestedRelationManagerData.test.ts +21 -0
- package/src/orm/modelDefaults.ts +21 -0
- package/src/pageData.ts +267 -47
- package/src/react/AppShell.tsx +55 -4
- package/src/react/PendingSuggestionApplierRegistry.ts +80 -0
- package/src/react/PendingSuggestionOverlayRegistry.ts +54 -0
- package/src/react/PendingSuggestionsContext.tsx +172 -0
- package/src/react/SchemaRenderer.tsx +504 -95
- package/src/react/cells/EditableCell.tsx +11 -2
- package/src/react/fields/CheckboxListInput.tsx +23 -2
- package/src/react/fields/ColorInput.tsx +22 -2
- package/src/react/fields/DateTimeInput.tsx +22 -2
- package/src/react/fields/FieldShell.tsx +167 -3
- package/src/react/fields/FileUploadInput.tsx +21 -2
- package/src/react/fields/KeyValueInput.tsx +32 -2
- package/src/react/fields/RadioInput.tsx +23 -2
- package/src/react/fields/SelectFieldInput.tsx +25 -2
- package/src/react/fields/SliderInput.tsx +20 -2
- package/src/react/fields/TagsInput.tsx +20 -2
- package/src/react/fields/ToggleFieldInput.tsx +23 -2
- package/src/react/index.ts +18 -0
- package/src/relationManagerData.test.ts +451 -2
- package/src/routes.ts +58 -2
- package/src/schema/Html.ts +2 -2
- package/src/schema/Markdown.ts +2 -2
- package/src/schema/Section.ts +17 -0
- package/src/schema/Wizard.ts +67 -0
- package/src/schema/containers.test.ts +90 -0
- package/src/schema/resolveSchema.test.ts +50 -0
- package/src/schema/resolveSchema.ts +79 -1
- package/src/schema/sanitize.ts +13 -4
- package/src/sessionFilters.test.ts +23 -0
- package/src/sessionFilters.ts +11 -1
- package/src/styles/file-upload.css +13 -0
- package/src/vite.ts +9 -2
package/CLAUDE.md
CHANGED
|
@@ -24,7 +24,7 @@ Pilotiq.make() builder → pilotiq([panels]) provider → registerPilotiqRoutes(
|
|
|
24
24
|
Deep notes for many of these also live in `~/.claude/projects/-Users-sleman-Projects-pilotiq/memory/`.
|
|
25
25
|
|
|
26
26
|
- `src/Pilotiq.ts` — Builder: `.path / .branding / .theme / .layout / .resources / .globals / .pages / .schema / .guard / .user(req=>userOrNull) / .use`. Exposes `pilotiq.resolveUser(req)` for routes.
|
|
27
|
-
- `src/RelationManager.ts` — **Plan #11** abstract base for parent-scoped projections. Required `static relationship` (matches a key on the parent model's `static relations` map; doubles as URL segment). Optional `label / labelSingular / icon / recordTitleAttribute / relatedResource`. Static `form(form, ctx) / table(table, ctx) / detail(record, parent)` configurators (mirror Resource shape minus URL ownership — no `slug`, no `pages()`). `ctx: RelationManagerContext` carries `basePath / parentSlug / parentId / relationship / parentRecord / related? / mode` so user code can wire `Action.relationCreate / relationEdit / relationDelete(M, ctx)` (or the M2M sibling factories) from inside `static table()` without threading basePath / parentId by hand. **`mode: 'hasMany' | 'belongsToMany' | 'morphMany' | 'morphTo'`** is auto-derived from `parentModel.relations[rel].type` via `getRelationType` + `normalizeRelationMode` in `pageData.relationManagerData` (and at registration time in `routes.ts`). `belongsToMany` flips into pivot-mutation mode; `morphMany` / `morphOne` collapse into `'morphMany'` (parent-side polymorphic — auto-fills `<morphName>Id` + `<morphName>Type` on create + edit); `morphTo` is the child-side polymorphic (no auto-actions, no auto-discovery — set `static relatedResource` explicitly); everything else collapses to `'hasMany'`. Overrides may drop the trailing `ctx` parameter (TS allows narrower override signatures). Form lifecycle hooks (`mutateDataBefore*`, `before/after*`, `save / handleCreate / handleUpdate`) — same shape as `Resource.form()`. Seven `can*` async predicates — `canViewAny / canView / canCreate / canEdit / canDelete / canAttach / canDetach`, defaults all return `true`; the page-data builder defers to the related Resource's matching predicate when the manager hasn't overridden (reference-equality check on the prototype). **`canAttach / canDetach` are manager-only** — they don't fall through to the related Resource because attach/detach are pivot operations, not record operations. `safeManagerPolicy(M, method, Related, user, parent, child?)` — lives in RelationManager.ts so `Action.ts` can reuse it cycle-free; pageData re-exports for back-compat. Reserved relationship tokens (`edit / delete / restore / force-delete / _form / _action / _search / _uploads / _attach / _detach / _bulk-detach`) validated at panel boot. `src/schema/RelationTabs.ts` — schema element built by `buildRelationTabs(R, recordId, base, activeKey)`; auto-mounted on EditPage / ViewPage when `R.relations().length > 0
|
|
27
|
+
- `src/RelationManager.ts` — **Plan #11** abstract base for parent-scoped projections. Required `static relationship` (matches a key on the parent model's `static relations` map; doubles as URL segment). Optional `label / labelSingular / icon / recordTitleAttribute / relatedResource`. Static `form(form, ctx) / table(table, ctx) / detail(record, parent)` configurators (mirror Resource shape minus URL ownership — no `slug`, no `pages()`). `ctx: RelationManagerContext` carries `basePath / parentSlug / parentId / relationship / parentRecord / related? / mode` so user code can wire `Action.relationCreate / relationEdit / relationDelete(M, ctx)` (or the M2M sibling factories) from inside `static table()` without threading basePath / parentId by hand. **`mode: 'hasMany' | 'belongsToMany' | 'morphMany' | 'morphTo'`** is auto-derived from `parentModel.relations[rel].type` via `getRelationType` + `normalizeRelationMode` in `pageData.relationManagerData` (and at registration time in `routes.ts`). `belongsToMany` flips into pivot-mutation mode; `morphMany` / `morphOne` collapse into `'morphMany'` (parent-side polymorphic — auto-fills `<morphName>Id` + `<morphName>Type` on create + edit); `morphTo` is the child-side polymorphic (no auto-actions, no auto-discovery — set `static relatedResource` explicitly); everything else collapses to `'hasMany'`. Overrides may drop the trailing `ctx` parameter (TS allows narrower override signatures). Form lifecycle hooks (`mutateDataBefore*`, `before/after*`, `save / handleCreate / handleUpdate`) — same shape as `Resource.form()`. Seven `can*` async predicates — `canViewAny / canView / canCreate / canEdit / canDelete / canAttach / canDetach`, defaults all return `true`; the page-data builder defers to the related Resource's matching predicate when the manager hasn't overridden (reference-equality check on the prototype). **`canAttach / canDetach` are manager-only** — they don't fall through to the related Resource because attach/detach are pivot operations, not record operations. `safeManagerPolicy(M, method, Related, user, parent, child?)` — lives in RelationManager.ts so `Action.ts` can reuse it cycle-free; pageData re-exports for back-compat. Reserved relationship tokens (`edit / delete / restore / force-delete / _form / _action / _search / _uploads / _attach / _detach / _bulk-detach`) validated at panel boot. `src/schema/RelationTabs.ts` — schema element built by `buildRelationTabs(R, recordId, base, activeKey, user, parentRecord)`; auto-mounted on EditPage / ViewPage when `R.relations().length > 0` OR `R.getRecordPages()` is non-empty, plus on the three relation page roles for parent-context continuity. **Record sub-pages (2026-05-11):** `Resource.pages()` returns may include a `record: Record<string, typeof Page>` map for custom sub-pages mounted at `${resourceBase}/:id/${subPageSlug}`. Tabs surface in the strip between `__edit` and the manager tabs, in declaration order; gate on `await SubPage.canAccess(user, parentRecord)` (predicate widened with optional record arg — back-compat with existing `canAccess(user)` signatures). Boot validation rejects sub-page slugs that collide with reserved tokens, relation-manager `relationship` slugs, or fail the `[A-Za-z0-9_-]+` pattern. `PageMode` widened with `'record'`. Page data builder `resourceRecordPageData(pilotiq, slug, recordId, subPageSlug, req)` mirrors `resourceViewData`'s shape and runs `R.canAccess + R.canView + SubPage.canAccess` before resolving the sub-page's schema. The route + Vike dispatch share the relation-list URL slot (`${slug}/:id/${rel-or-subSlug}`); `dispatchPageData` tries the relation-manager lookup first, falls through to `resourceRecordPageData` when no manager matches. Plan + guide: `docs/plans/resource-record-sub-pages.md`, `docs/guide/record-sub-pages.md`. **Sub-nav follow-up (2026-05-03 cont'd):** the strip emits `[__view, __edit, …managers]` — both record-mode tabs are siblings rather than one-or-the-other. Each `__view` / `__edit` tab is gated on the corresponding page role being registered in `R.resolvePages()` (defaults ship both, but a `static pages()` override that drops one suppresses the matching tab so it can't 404). `activeKey` (`'__view'` / `'__edit'` / a manager's relationship key) selects the highlighted tab; `mode` parameter dropped — same fn produces every page's strip from a single shape. **Per-tab canX gating (2026-05-11):** the strip also evaluates the matching predicate per tab and drops entries the user can't reach — `__view` runs `R.canView(user, parentRecord)`, `__edit` runs `R.canEdit(user, parentRecord)`, each manager runs `safeManagerPolicy(M, 'canViewAny', Related, user, parentRecord)`. Predicates throwing fail closed (tab hidden); record-aware predicates skip when `parentRecord` is undefined (record-load failure surfaces a 404/403 on the route, so the strip stays consistent). After gating the strip may collapse to zero entries — `buildRelationTabs` then returns `undefined` (consistent with the no-managers branch). `buildNestedRelationTabs(R, M, base, step0, child1Id, activeKey, user, child1Record)` mirrors the same shape for the depth-2 strip; sibling nested manager tabs gate on `safeManagerPolicy(N, 'canViewAny', Related, user, child1Record)`; the back-link `__view` stays unconditional (user already passed `M.canViewAny` to reach the page). Routes still enforce in front of the data builder — this is presentation polish, not security.
|
|
28
28
|
- `src/orm/modelDefaults.ts` — `ModelLike / ModelQuery` structural interfaces + `modelSave / modelLoadRecord / modelTableRecords` helpers. `defaultPages(R)` installs them as Form/Table sentinels when `R.model` is set. Pilotiq has zero runtime dep on `@rudderjs/orm`. Plan #11 additions: `ModelLike.relatedQuery?(parent, name)` optional override; default reads `parent.related(name)` (rudder ORM convention). `defaultRelatedQuery / resolveRelatedQuery / modelRelationTableRecords` helpers feed `Table.records()` for managers.
|
|
29
29
|
- `src/Cluster.ts` — Filament-style structural cluster (Tier-3, 2026-05-05 cont'd¹⁴). `static label / slug / icon / navigationGroup / navigationSort / navigationLabel / navigationIcon / navigationBadge / navigationBadgeColor / navigationParentItem / canAccess(user) / landingPage`. Resources / Globals / Pages opt in via `static cluster = MyCluster`; URLs gain `${base}/${cluster.slug}/${child.slug}/...` prefix and the child nests under the cluster's nav entry. Boot validates dup slugs, reserved tokens (`_*`, `theme`, `api`), dangling references, top-level slug collisions, and landing-page sanity (must be in `pages()` AND back-reference the cluster). Cluster URL = first accessible child or `landingPage` URL when set. `Cluster.canAccess(user)` AND'd with child predicates — both must pass; failing cluster gate drops every child from nav AND 403s every cluster-prefixed route. Helpers `clusterPaths.ts` exports `resourceBasePath / globalBasePath / pageBasePath / clusterBasePath` used everywhere URLs are built (`routes.ts`, `pageData.ts`, `Resource.getGlobalSearchResultUrl`, `Action` factories via structural `ResourceLike.cluster`). Vite plugin emits `clusterSlugsByBasePath` map alongside `componentRegistry` in `_components.ts`; auto-gen route stubs detect cluster prefix via `clusterOffset(parts)` and shift their part-index reads accordingly so SPA nav works on both shapes. v1 limits: no nested clusters, no aggregated badges, no cluster-internal sidebar. Plan + guide: `docs/plans/clusters.md`, `docs/guide/clusters.md`.
|
|
30
30
|
- `src/Resource.ts` — abstract class with **static** methods `label / labelSingular / slug / icon / model / form / table / detail / deleteRecord / pages / resolvePages / relations / getSlug`. Resources register as classes. `model?: ModelLike` opts into auto-wired CRUD. **Nav metadata (Plan #9):** `navigationGroup / navigationSort / navigationLabel / navigationIcon / navigationBadge / navigationBadgeColor / navigationParentItem` (parent ref by JS class name, not slug). Plus `recordTitleAttribute`. **Breadcrumb override (2026-05-06 cont'd⁴):** `breadcrumb?: string` static + `getBreadcrumb()` accessor — falls through to `label` when unset. Reads through every Phase C breadcrumb path (resource list/create/view/edit + the relation prefix used by depth-1 + depth-2 chains). Pair with a longer `label` when the sidebar / page-title plural reads better long ('Blog Posts') but the breadcrumb chain reads tighter short ('Posts'). **Authorization (Plan #10):** six async predicates default `true` — `canAccess / canViewAny / canView / canCreate / canEdit / canDelete`. Throwing → fail closed. Opaque user. **Global search (Plan #12):** `globalSearch` toggle (default `false` — opt-in), `globallySearchableAttributes()` defaults to `recordTitleAttribute` + every `Column.searchable()` from the configured table, `getGlobalSearchResultTitle / Subtitle / Url(record, base)` with sensible defaults (record[recordTitleAttribute] → name → title → id; URL = `${base}/${slug}/${id}`), `getGlobalSearchQuery(needle)` override returns a `ModelQuery` for joined / FTS / non-LIKE backends. **Plan #15 widgets:** `static headerSchema(ctx?) / footerSchema(ctx?)` return widget elements rendered above / below the resource list table; resource-scope widget endpoint `POST {base}/{slug}/_widget/:id` runs `canAccess + canViewAny` in front of widget visibility check. **Filter persistence (Tier-3, 2026-05-05 cont'd¹¹):** `persistFiltersInSession = false` opt-in flag — when true, the GET list handler stashes the URL filter slice (filters / `group` / `search` / `sort` / `perPage`; `page` + `tab` excluded) on `req.session` and 302-redirects bare visits back to the last-applied state. No-ops without `@rudderjs/session`. Helpers in `src/sessionFilters.ts`; guide `docs/guide/filter-persistence.md`. **Defer loading (Tier-3, 2026-05-05 cont'd¹²):** `deferLoading = false` opt-in flag — when true, the SSR pass on the list page calls `tagTableDeferred(elements, '${indexUrl}/_table')` BEFORE `loadTableRecords`, marking every Table on the page as deferred and stamping a `tableUrl`. `loadTableRecords` short-circuits the records handler when `Table.isDeferred()` returns true (URL chrome state — current sort / search / page — still mirrors). The renderer's `<TableRenderer>` shell handles the deferred branch: paints `<TableSkeleton>` on first frame, fetches `tableUrl + window.location.search` after mount with `Accept: application/json`, replaces the skeleton with the response's `tables[0]` meta. New route `GET {base}/{slug}/_table` (registered only when `R.deferLoading=true`) calls `resourceTableData()` which re-runs the same data builder WITHOUT the deferred flag — records load, per-row stamping runs, summaries compute, and `collectTableMetas(schemaData)` returns every `type:'table'` meta as a flat array. SPA nav re-runs SSR → re-paints skeleton → re-fetches; every nav pays one skeleton frame. Composes with `persistFiltersInSession` (bare-visit 302 redirect happens BEFORE the deferred-load decision). Guide `docs/guide/defer-loading.md`. **Soft deletes (Plan #13):** `softDeletes = false` opt-in flag + `deletedAtColumn = 'deletedAt'` column-name override. Two new async predicates: `canRestore(user, record)` (default `true`) and `canForceDelete(user, record)` (default delegates to `canDelete` via `this.canDelete(user, record)` for fail-closed inheritance). Both flags must opt in (rudder side `Model.softDeletes = true` AND pilotiq `Resource.softDeletes = true`); routes throw a clear boot error when only one side is set or when `model.restore / forceDelete` are missing. Wires up: `TrashedFilter` auto-injection on the list page; `Action.restore / forceDelete / bulkRestore / bulkForceDelete` factories; "moved to trash" framing on the standard delete success notification; auto-visibility on `Action.delete` (hides on already-trashed rows) / `Action.restore` + `forceDelete` (show only on trashed rows). Two new routes per soft-delete resource: `POST /:slug/:id/restore` and `POST /:slug/:id/force-delete` (both look up records via `query.withTrashed()` to bypass default scope).
|
|
@@ -35,7 +35,8 @@ Deep notes for many of these also live in `~/.claude/projects/-Users-sleman-Proj
|
|
|
35
35
|
- `src/defaultGlobalPages.ts` — same factory pattern for `Global`; default returns `{ edit }`.
|
|
36
36
|
- `src/Column.ts` — `Column.make(name).label().sortable().searchable()`. Cosmetic builders + built-in formatters (`.dateTime, .since, .money, .numeric, .limit, .words, .characters` (alias for `.limit`)). Server-side `.formatStateUsing((value, record) => string)` stashes per-row results on `row._formatted[name]`. **Footer summaries:** `.summarize([Sum/Average/Count/Range])` — `loadTableRecords` computes aggregates over the rendered rows and stamps `TableMeta.summaries[colName]` (`SummaryResult[]`); per-page only in v1. **Rich-display chrome (Filament-parity Tier-2, 2026-05-07 cont'd¹²):** `.listWithLineBreaks() / .bulleted() / .copyMessage(message?) / .markdown() / .html()` plus `sanitize / allowRaw` for the rich-text pair. `listWithLineBreaks` and `bulleted` apply only to array values (bulleted wins when both are set). `copyMessage` mounts a `CellCopyButton` after the cell value (the message doubles as the toast text; default `'Copied!'`). `markdown / html` are mutually exclusive and stamp `richText: 'markdown' | 'html'` onto the meta — `dispatchTable` server-renders matching cells through `marked` (markdown) or passthrough (html), runs the result through `sanitize-html` against `DEFAULT_SANITIZE_CONFIG` (or the user's widened config / `allowRaw`), and stamps `row._formatted[col.name]` + `row._richtextCells[col.name] = true` so the renderer mounts the existing prose-sm `dangerouslySetInnerHTML` path. `formatStateUsing` always wins over `markdown/html` (declared first by the user — assumed deliberate); the auto-richtext (Tiptap) walker filter excludes `isRichText()` columns so they don't double-render.
|
|
37
37
|
- `src/summarizers/` — `Summarizer` base + `Sum / Average / Count / Range` subclasses. Each has `.label(text)` (rendered before the value) and `.format((n) => string)` for currency/locale formatting (Count ignores format). `compute(values)` filters out null/undefined/empty/NaN before aggregating — `Number(null)` returning 0 would otherwise pollute averages and ranges.
|
|
38
|
-
-
|
|
38
|
+
- **`Column.toggleable(opts?)` (2026-05-10 cont'd⁸):** opt-in user-visibility chrome. Bare `toggleable()` lets the user hide the column from the toolbar's "Columns" dropdown; `toggleable({ initiallyHidden: true })` starts off-screen. State persists to `pilotiq.table.<currentPath>.columns.<col>` localStorage ('1' hidden / '0' visible / null falls back to `initiallyHidden`). Renderer adds a `<ColumnsToggleDropdown>` toolbar trigger next to FilterPopover / SortByPicker; uses `closeOnClick={false}` so users can toggle multiple columns without re-opening. `visibleColumns = columns.filter(c => !hiddenColumns.has(c.name))` replaces `columns` in the TableHead loop, body cells loop, per-group + footer summaries, and the empty-state colSpan. Hidden state is presentational only — data still loads server-side so sort/filter/group on a hidden column keeps working. Sparse meta — `toggleable` key absent unless the column opts in.
|
|
39
|
+
- `src/columns/` — `TextColumn / BadgeColumn / IconColumn / BooleanColumn / ImageColumn / TextInputColumn / ToggleColumn / SelectColumn`. Each sets `columnType` via `setColumnType()`; renderer branches on it. `TextColumn.make(name)` is the explicit text-cell factory; `Column.make(name)` is an alias kept for back-compat — both produce identical wire shape (`columnType` defaults to `'text'`, omitted from meta). **Editable cell columns (2026-05-03):** `TextInputColumn / ToggleColumn / SelectColumn` flip `Column.isEditable() === true`; per-row `R.canEdit(user, row)` gate runs in `loadTableRecords` (via the new `LoadTableHooks.canEdit` callback threaded from `resourceIndexData`); successful gates stamp `_cellEditable[col]: true` + `_cellDisabled[col]: true` on the row, and `pageData.tagCellEditUrls(elements, indexUrl)` walks them after to add `_cellEditUrls[col]` (parallel to `tagFormStateUrls / tagTableReorderUrls`). PATCH route at `POST {base}/{slug}/:id/_cell/:column` body `{ value }`; coerce + validate + `R.model.update(id, { [col]: value })`. Boot guard requires `R.model.update` whenever an editable column is present. Renderer in `react/cells/EditableCell.tsx` (`CellTextInput / CellToggle / CellSelect` + `pickEditableCell()`) — debounced (500 ms default) for TextInput, immediate for Toggle / Select; optimistic local state + rollback on failure with error toast; `data-no-row-nav` so cell controls don't trigger row click; opt-in `.confirm(message)` gates the PATCH behind a Dialog. **`SelectColumn.options(record => …)` per-row resolver (2026-05-10 cont'd⁵):** function form receives the raw record and may return a Promise; runs in parallel with sibling resolvers inside the per-row `if (allowed)` block in `dispatchTable.ts` (gated behind canEdit so hidden cells don't pay the resolver cost). Stamps `row._cellSelectOptions[col.name]: ColumnSelectOption[]`; renderer's `<CellSelect>` reads `props.rowOptions` first, falls back to `col.selectOptions`. Resolver-only columns omit `selectOptions` from meta (per-row stamp wins); throwing resolver leaves the slot unset on that row only — others still stamp, and the cell falls back to whatever static `.options()` is set (or empty list) so one bad row doesn't break the whole table. Mixing static + resolver: re-calling `.options()` replaces the prior set in either direction.
|
|
39
40
|
- `src/PilotiqRegistry.ts` — globalThis-backed singleton, `findByPath()` for route matching.
|
|
40
41
|
- `src/sessionFilters.ts` — Tier-3 filter persistence helpers. `Resource.persistFiltersInSession = true` opts in; the GET list handler in `routes.ts` writes the active query slice (filters / `group` / `search` / `sort` / `perPage`; `page` + `tab` excluded) to `req.session` under `pilotiq:filters:<basePath>:<slug>` on every non-bare visit, and 302-redirects bare visits (zero query params) to the persisted slice. Duck-typed `req.session.get / put` (mirrors `notifications/flash.ts`) so it no-ops when `@rudderjs/session` isn't installed. Idempotent — short-circuits the `put()` when the slice deep-equals the stored value to avoid `Set-Cookie` churn on revisits. v1 = one slot per resource (all tabs share one filter slot); guide: `docs/guide/filter-persistence.md`.
|
|
41
42
|
- `src/PilotiqServiceProvider.ts` — Provider + `pilotiq()` factory.
|
|
@@ -63,7 +64,7 @@ Deep notes for many of these also live in `~/.claude/projects/-Users-sleman-Proj
|
|
|
63
64
|
- `src/schema/` — Unified `Element` model:
|
|
64
65
|
- `Element.ts` — abstract base. Contract: `getType(), toMeta()`, optional `_children: Element[]`. **Plan #8 layout-level state:** `visible(rule) / hidden(rule)` accept `boolean | (ctx: LayoutContext) => bool | Promise<bool>` — resolver drops hidden non-Field/non-Action layouts. `columnSpan(n) / columnStart(n) / columnOrder(n)` emit under `meta._layout` and map to Tailwind `col-span-* / col-start-* / order-*` (1..12 clamp).
|
|
65
66
|
- **Display:** `Text, Heading, Alert, Divider, Image, Icon, Markdown, Html, UnorderedList`. **`UnorderedList` (2026-05-04 cont'd):** `UnorderedList.make(items?: string[]).items([…]).color(TextColor).size(TextSize).weight(TextWeight)` — bullet list display prime; reuses the `Text` class maps so styling matches neighbouring text in a detail view. **Text formatting (2026-05-03 cont'd):** `.color('default'|'muted'|'primary'|…) / .size('xs'|'sm'|'base'|'lg'|'xl') / .weight('normal'|'medium'|'semibold'|'bold') / .badge(v=true) / .badgeColor(BadgeColor)` — pill rendering reuses `BADGE_COLOR_CLASSES`; bare `Text.make()` keeps the prior `text-sm text-muted-foreground` defaults. **Image:** `Image.make(url).alt(t).width(n).height(n).size(n).rounded()|.circle()`. **Icon:** `Icon.make(registryName).size(px).color(IconColor).label(t)` — string-only (registry-resolved); for component-typed icons used by Resource/Page/Global statics see `IconValue`. **Markdown / Html (2026-05-03 cont'd):** read-only display primes (the `MarkdownField` / `RichTextField` editor counterparts). `Markdown.make(source).gfm(b=true).breaks(b=false).prose(b=true).size('sm'|'base'|'lg')` server-renders the source via `marked` so initial paint shows formatted HTML with no parser shipped to display-only pages. `Html.make(html).prose().size()` passes raw strings through (use for legacy CMS columns or already-rendered fragments). Both wrap in a `prose max-w-none` container with optional `prose-sm` / `prose-lg` modifier when `prose=true` (default). **Sanitized by default (2026-05-07 cont'd⁷)** via `sanitize-html` against `DEFAULT_SANITIZE_CONFIG` (`schema/sanitize.ts`); strips `<script>` / `<iframe>` / `javascript:` / inline event handlers / `style=`. Three escape hatches on both primes: `.allowRaw()` (sugar) / `.sanitize(false)` (explicit) / `.sanitize({ allowedTags, allowedAttributes, allowedSchemes })` widening config. The renderer collapses both to a single `case 'markdown' | 'html'` branch in `renderElement` since shapes are identical (server-converted html string + prose flag). **Head-safe (2026-05-07 cont'd⁸):** `MetaTag.make({ name | property | httpEquiv | charset, content? }) / LinkTag.make({ rel, href?, mimeType? }) / ScriptTag.make({ src? | body?, async?, defer?, dataAttributes? }) / StyleTag.make(css, { nonce? })` — value-Element tags emitted ONLY by `panels::head.* / panels::scripts / panels::styles` render-hook callbacks. Body-level Elements inside head slots get skipped with a console warning. `mimeType` on Link/Script renames the HTML `type=` attribute (which collides with the wire-shape discriminator); renderer maps back. Mounted via `<HeadHooks position="start"|"end">` from `@pilotiq/pilotiq/react` inside the auto-generated `+Head.tsx`. **Containers:** `Card, Section, Tabs/Tab, Grid, Group, Fieldset, Split, Wizard/Step` (Plan #8). **Section polish (Plan #8):** `icon(name) / badge(text) / aside(v=true) / compact(v=true) / persistCollapsed(key?)` (key auto-derived from page slug + title). `aside()` flips into right-rail when nested in `Split`. `persistCollapsed` writes `pilotiq.section.<key>` to localStorage on toggle. **`dense(v=true)` (2026-05-03)** — orthogonal to `compact()`: `compact` trims outer padding + heading size; `dense` trims the inner grid `gap` between children (gap-2 / 8px vs gap-4 / 16px). Compose both for a settings-page look. **`secondary(v=true) / afterHeader([Action…])` (2026-05-07 cont'd¹¹)** — Filament v5 chrome polish: `secondary` flips the surface to `bg-muted/40 border-muted` so the section recedes beneath a primary card; `afterHeader` mounts right-aligned `Action[]` buttons in the section header (resolved through the standard walker so `.visible() / .disabled()` rules evaluate the same way as anywhere else; v1 is `Action[]` only — Element-typed children would require a second resolver pass).
|
|
66
|
-
- `Wizard.ts` — `Wizard.make().steps([Step.make(label).icon(name).description(d).schema([…])]).skippable().startOnStep(n).persist(false)`. All steps' children resolve every cycle so cross-step `$get` works; client renderer hides inactive steps via `display:none` so controlled inputs survive transitions. Active step persists to `pilotiq.wizard.<formId>.step` localStorage key. Next button POSTs `{ step, values }` to `Form.wizardUrl` — 200 advances, 422 stamps inline errors, missing url advances immediately.
|
|
67
|
+
- `Wizard.ts` — `Wizard.make().steps([Step.make(label).icon(name).description(d).schema([…])]).skippable().startOnStep(n).persist(false)`. All steps' children resolve every cycle so cross-step `$get` works; client renderer hides inactive steps via `display:none` so controlled inputs survive transitions. Active step persists to `pilotiq.wizard.<formId>.step` localStorage key. Next button POSTs `{ step, values }` to `Form.wizardUrl` — 200 advances, 422 stamps inline errors, missing url advances immediately. **Wizard nav polish (2026-05-10):** `.persistStepInQueryString(key='step'|true|false)` mirrors the active step to the URL as `?<key>=N` (1-based) via `history.replaceState` (purely client-side state sync, no SSR re-fetch); URL wins over localStorage on initial mount so deep-linking works; multi-wizard pages need distinct keys to avoid collisions. `.submitAction(a => a.label('Create campaign')) / .nextAction(...) / .previousAction(...)` customize the chrome of the built-in nav buttons — the customizer receives a framework-built default `Action` (Submit / Next / Back) and returns a customized clone (or fresh `Action`); chrome (label/icon/color/size/outlined/iconOnly/tooltip/disabled rules) carries through to the rendered button while click behavior stays hardwired (advance / recede / submit-form). `submitAction` is the opt-in case: by default the wizard renders a hint pointing at the page-level Save; setting `submitAction` mounts a real `<button type="submit">` inside the wizard chrome on the final step (pair with `CreatePage.getFormActions(R) → []` to suppress the page-level Save when the wizard is the entire form). Resolved through `resolveSchema`'s `if (el instanceof Wizard)` branch so `.visible(false)` on a customizer cleanly drops the slot from meta (renderer falls back to default chrome).
|
|
67
68
|
- `Split.ts` — two-column layout. `.from('left' \| 'right').gap(n).schema([main, aside])`. Aside child detected via `Section.aside()` marker; falls back to second child. Renders `flex flex-col @md:flex-row` with `@container` query so nested Splits behave.
|
|
68
69
|
- `Fieldset.ts` — labeled border container. `.columns(1\|2\|3).schema([…])`. `<fieldset><legend>` semantics, lighter than Section.
|
|
69
70
|
- `Group.ts` — chrome-less container. Pass-through `<div>`. Useful for visibility gating without imposing border/heading.
|
|
@@ -75,11 +76,11 @@ Deep notes for many of these also live in `~/.claude/projects/-Users-sleman-Proj
|
|
|
75
76
|
- `src/elements/` — first-class container Elements:
|
|
76
77
|
- `Form.ts` — `Form.make().schema([...])` + lifecycle setters (`validate, mutateData*, before*, save, handleCreate/Update, after*, redirectAfterSave, loadRecord, fillFromRecord, mutateFormData*, savedNotification, createdNotification, disableSavedNotification`). Render-time setters `withValues / withErrors / withStateUrl / withWizardUrl`. `toMeta()` emits `formId / method / action / values / errors / stateUrl / wizardUrl`. Auto-generated `formId`; multi-form pages discriminate via hidden `_formId` input.
|
|
77
78
|
- `Table.ts` — `Table.make().columns([...]).records(fn).defaultSort.paginate`. `records(ctx) → { rows, total }` or bare row array. Render setters `withRows / withSort / withSearch / withPage`. **Grouping (Tier-2 follow-up to Batch B, 2026-05-03):** `Table.defaultGroup(string | TableGroup)` widened — bare-column form still works (band rows by `column`), `TableGroup` form auto-registers in `groups([…])`. `Table.groups([TableGroup.make(col).label(text).collapsible().collapsed().getTitleFromRecordUsing(r=>str).getDescriptionFromRecordUsing(r=>str).date()])` — multi-option group selector. URL key `?group=col` selects the active option; `?group=` (empty) explicitly disables; absent falls back to `defaultGroup`. Reserved query keys: `search/sort/page/perPage/group`. `parseActiveGroup(query, table)` reconciles URL → active column. `dispatchTable.loadTableRecords` calls `withActiveGroup(col)` after reconciliation; `toMeta` then emits `defaultGroup` as the resolved active column (NOT the configured one). Per-row stamping: `_groupValue` (raw / `YYYY-MM-DD` for date), `_groupTitle?` (resolved title — user handler wins over `date()`'s default formatter), `_groupDescription?`. Throwing handlers fall silent. Renderer ships a `<TableGroupPicker>` Select dropdown above the table when 2+ groups (or 1 with rich metadata); collapsible heading rows show a chevron + per-group fold state persisted at `pilotiq.table.<currentPath>.groups.<column>.<value>`. **Per-group summarizers (2026-05-03 cont'd):** when an active group is set AND at least one column has `summarize([…])`, dispatcher also computes summaries within each group bucket and stamps `TableMeta.groupSummaries: Record<groupValue, Record<colName, SummaryResult[]>>`; renderer emits an inline summary row at the END of each group band, aligned to the global `<tfoot>` columns, suppressed when the group is collapsed. **Manual group ordering (2026-05-03 cont'd):** `TableGroup.orderUsing((a, b) => number)` overrides the default alphabetic comparator on group keys; sugar helper `orderByKeys([…])` exported alongside the class. `dispatchTable.sortRowsByGroupValue` accepts the comparator; empty-bucket-last + within-group stability stay structural (run before/after the user's comparator respectively). `scopeQueryByKey` (click-to-drill-in) still deferred — coupled enough to filter wiring to deserve its own pass. **`Table.queryStringIdentifier(id)` (Tier-3, 2026-05-05 cont'd¹³):** namespaces every URL key for one table under `${id}_<key>` so multiple tables on one page (custom-page case) don't fight over `?search=` / `?sort=` / etc. Server-side: `parseTableQuery / parseFilterValues / parseActiveGroup` accept an optional `prefix`; `loadTableRecords` reads each table's prefix from `Table.getQueryStringIdentifier()` and parses its slice independently. Renderer-side: `prefixK(prefix, key)` mirrors the join inline, threaded into `buildTableQuery`, the search input (`name="<id>_search"`), `FilterSelect / FilterMultiSelect / FilterDateRange / FilterForm / ActiveFiltersBar / FilterPopover / TableGroupPicker` (all accept `prefix`), the `urlGroup` reader, and a new `<SearchFormHiddenInputs prefix>` that mirrors current URL state into the native search form so a bare `<form method="get">` Enter-submit doesn't drop sort / filter selections (or other tables' params). `sessionFilters.ts` extends its excluded-page-key check to drop both bare `page` and any `<prefix>_page` so persistFiltersInSession composes; deferred `_table` JSON endpoint composes naturally (server reads each table's prefix). Empty / non-`[A-Za-z0-9_-]+` ids throw at config time. Guide: `docs/guide/query-string-identifier.md`. **`Table.filtersLayout(position)` (Filament v5 parity, 2026-05-06 cont'd⁸):** swaps the toolbar Filters popover for an inline strip in the matching slot. `'modal'` (default) preserves today's behaviour; `'above-content'` always-visible strip above the table; `'above-content-collapsible'` adds a toolbar toggle that flips a `pilotiq.table.<currentPath>.filters.open` localStorage slot (defaults open when the URL carries any filter value); `'below-content'` strip after pagination. Inline modes hide the active-filter pill row — every widget already shows its current value, and per-widget clear affordances stay. Sidebar positions (`BeforeContent` / `AfterContent`) reshape the page rather than the table chrome and are deferred until a consumer asks. Pure renderer change — no ORM contract changes, no URL-state changes.
|
|
78
|
-
- `TableGroup.ts` — value-object primitive owned by `Table.groups([…])`. Fluent setters: `label / collapsible / collapsed / getTitleFromRecordUsing / getDescriptionFromRecordUsing / date / orderUsing(comparator)`. Helpers `bucketDateValue(raw) → 'YYYY-MM-DD'`, `formatDateBucketTitle(raw) → 'May 4, 2026'`, and `orderByKeys([…]) → comparator` exported for downstream tests / custom formatters.
|
|
79
|
+
- `TableGroup.ts` — value-object primitive owned by `Table.groups([…])`. Fluent setters: `label / collapsible / collapsed / getTitleFromRecordUsing / getDescriptionFromRecordUsing / date / orderUsing(comparator) / scopable(b=true) / scopeQueryByKey(fn) / getKeyFromRecordUsing(fn)`. Helpers `bucketDateValue(raw) → 'YYYY-MM-DD'`, `formatDateBucketTitle(raw) → 'May 4, 2026'`, and `orderByKeys([…]) → comparator` exported for downstream tests / custom formatters. **Click-to-drill (2026-05-11):** `.scopeQueryByKey((q, key) => q.where(col, '=', key))` opts heading text into a real `<a href>` that drills the table into one bucket — banding suppressed, "Drilled into <Label>: <Value>" chip mounts above the table with × to clear. `.scopeQueryByKey()` / `.getKeyFromRecordUsing()` both auto-arm `.scopable(true)`. URL state: dedicated `?<prefix>groupKey=<value>` (added to `RESERVED_QUERY_KEYS` so filter names can't collide); `?page` resets to 1 on drill-in; `<prefix>groupKey` excluded from `persistFiltersInSession` slice (drill-in is page-state, not filter-state). `dispatchTable.parseActiveGroupKey(query, table, activeCol, prefix?)` reconciles the URL value against the registered scopable group; threads through `ctx.groupScope: { group, key }` into the records handler so `modelTableRecords` + `modelRelationTableRecords` splice the scoper after filters/tab. Default scoper for `.date()` groups installs a whole-day range (`>=` `YYYY-MM-DD 00:00:00` + `<=` `YYYY-MM-DD 23:59:59`); plain groups default to exact-match. Per-group summaries suppressed in drilled-in render; global `tfoot` summary still computes over the visible bucket. Renderer's group heading becomes a `<GroupHeadingLink>` (SPA-nav via `useNavigate()`, cmd-click / right-click "open in new tab" works); collapsible chevron stays as a separate button so folding doesn't drill in. Plan + guide: `docs/plans/table-group-scope-query-by-key.md`, `docs/guide/grouping.md`.
|
|
79
80
|
- `dispatchForm.ts` — `dispatchFormSubmit(form, body, ctx)` runs full lifecycle. Form-level validator errors land under `_form` key. `findForms / selectForm` for multi-form. **Plan #5:** `applyStateUpdate(form, values, changed, ctx)` finds the changed field, coerces only that one, runs `afterStateUpdated`, returns `{ values, dirty }`. **Plan #8:** `findWizardStepFields(formChildren, stepIndex)` walks the form's tree, returns the children of the requested step (or `undefined` when no Wizard / step out of range).
|
|
80
81
|
- `dispatchTable.ts` — `parseTableQuery / loadTableRecords`. Walks tree, calls every `Table.records(ctx)` in parallel, mirrors state back.
|
|
81
82
|
- `dispatchAction.ts` — `findActions / parseActionBody / dispatchAction`. Routes auto-stamp `Action.dispatchUrl()`.
|
|
82
|
-
- `src/fields/` — `Field` base + 20 subclasses (`TextField, EmailField, NumberField, SelectField, TextareaField, ToggleField, DateField, SlugField`, **Plan #6:** `HiddenField/Hidden, CheckboxField/Checkbox, RadioField/Radio, CheckboxListField/CheckboxList, SliderField/Slider, ColorPickerField/ColorPicker, DateTimePickerField/DateTimePicker, KeyValueField/KeyValue, FileUploadField/FileUpload`, **Plan #14:** `RepeaterField/Repeater`, **Tier-2 micro-plans (2026-05-04):** `ToggleButtonsField/ToggleButtons` — sugar over Radio with chip rendering; same `OptionsResolver` shape; no separate coerce branch (string passthrough). `TagsInputField/TagsInput` — free-text tag chips; `string[]` value; `.suggestions(string[]|resolver) / .separator(',') / .splitKeys(['Enter']) / .reorderable() / .maxTags(n)`; wire format = JSON-encoded array in a single hidden input; new `tagsInput` coerce branch parses back to `string[]`. **`reorderable()` (2026-05-03):** chips become draggable via native HTML5 drag-and-drop with a 2px vertical drop indicator and a grip-icon affordance; reuses `reorderRows` helper from `RepeaterInput`. Off by default — most tag sets are insertion-ordered or alphabetized. **`MarkdownField/Markdown` (2026-05-04 cont'd)** — plain-markdown editor; raw string value (same wire format as `TextareaField`, no new coerce branch); `.toolbarButtons([…]) / .disableToolbarButtons([…]) / .minHeight(css) / .maxHeight(css) / .fileAttachmentsDirectory(d) / .fileAttachmentsVisibility('public'\|'private')`. Default toolbar = 10 buttons (`bold/italic/strike/link/heading/bulletList/orderedList/blockquote/codeBlock/attachFiles`). Renderer ships a tab switcher (Write / Preview); preview HTML is rendered client-side via `marked` (`gfm: true, breaks: false`), no DOMPurify in v1 (admin-trusted authors). `attachFiles` reuses the existing `_uploads` route + `UploadAdapter`; the button is stripped server-side when no adapter is registered via the new `RenderContext.hasUploadAdapter` flag (see "RenderContext" note below). Paste-image splices ``; ⌘B/⌘I/⌘K shortcuts). Visibility flags + condition callbacks (`showWhen, hideWhen, disabledWhen`), validators via `.validate(v|v[])`. **Plan #5:** `Field.live(opts?: boolean | { onBlur?: boolean; debounce?: number })` marks re-resolve trigger; `Field.afterStateUpdated((value, ctx) => …)` server hook; `SelectField.options(fnOrArray)` async-aware; `FieldCondition` widened from `(record) => bool` to `(ctx: ConditionContext) => bool`. Conditions skip when both `record` and `values` are undefined. **`Field.afterStateUpdatedJs(body)` (2026-05-04 cont'd, Tier-2 follow-up):** client-only counterpart to `afterStateUpdated`. Body string compiled via `new Function` (CSP `unsafe-eval` required) with `$state / $get / $set` bound; cached by source-string identity in `react/fieldJsHandler.ts`; runs synchronously on every change (no `live()` required, no roundtrip). Compose with the server hook — JS runs first, server response (when `live()` is also set) overlays sibling values. Repeater/Builder rows: dotted-path `$get / $set` route through `readNestedValue / writeNestedValue` (snapshot-then-overlay so `$get(thisField)` matches `$state`). `tagFormStateUrls` stamps `stateUrl` for forms with EITHER `live()` OR `afterStateUpdatedJs` so the `FormStateProvider` mounts (the endpoint is unused for JS-only forms; client only POSTs on `live`). **Plan #6 cross-field plumbing on `Field`:** `prefix(string|{icon}) / suffix(...) / helperText(text) / inlineLabel(v=true) / default(value) / dehydrated(false) / formatStateUsing(fn)`. **`inlineLabel()` (2026-05-04 cont'd)** mirrors the `Entry.inlineLabel` shipped with Plan #16 — `FieldShell` swaps to a `flex items-baseline gap-3` row with a `min-w-32` label column (default label-above unchanged); helperText still renders under the value. Bare `inlineLabel(false)` clears. `dehydrated(false)` drops the field from the POST body before validation. `OptionsResolver` extracted to `fields/optionsResolver.ts` and shared by SelectField/Radio/CheckboxList. FileUpload reads `ctx.uploadUrl` (panel-level URL stamped by `pageData.uploadCtx`). New coerce branches: `checkbox` (toggle-like), `slider` (number-like), `dateTime`, `checkboxList` (string[]), `color`, `keyValue` (JSON-string → object), `fileUpload` (URL string or string[]). **Plan #14 `RepeaterField`:** array-of-subschema field; `.schema([...]) / .columns(n) / .defaultItems(n) / .min/maxItems / .reorderable() / .collapsible().collapsed() / .accordion() / .cloneable() / .itemLabel(row=>str) / .addActionLabel(text)`. **`accordion()` (2026-05-06):** one-row-open-at-a-time mode; auto-arms `collapsible()`. Renderer swaps the per-row `collapsed[id]` map for a single `accordionOpenId: string | null` slot; persisted under `pilotiq.repeater.<formId>.<name>.accordion`. Compose with `collapsed()` for "all start closed" (default opens first visible row). Available on Builder too — same shape, persisted under `pilotiq.builder.<formId>.<name>.accordion`. **`expandAction(b) / expandAllAction(b?) / collapseAllAction(b?)` (2026-05-08, audit gap #7):** widens `RowButtonKind` from 7 → 10 slots. `expandAction` is a sibling of `collapseAction` for the *collapsed* state only (open state still routes through `collapseAction`; bare `collapseAction` continues to cover both states for back-compat). `expandAllAction / collapseAllAction` are opt-in field-header bulk chips — calling enables (with or without a `RowButton` override), auto-arms `collapsible()`. Renderer mounts via shared `<BulkCollapseHeader>` above the rows in both Repeater and Builder; accordion mode preserves "only one open" by opening the first visible row on `expandAll` and clearing `accordionOpenId` on `collapseAll`. Per-row mode iterates every row id and writes the `pilotiq.repeater|builder.<formId>.<name>.<rowId>` storage slot so reload restores the bulk state. Table mode skips the chrome (collapsing is meaningless on `<tr>` rows). All three serialize through the existing `serializeRowButtons` helper — no new wire-shape branch. Server-resolved `meta.rows: { id, children, itemLabel? }[]` + `meta.template`. `coerceFormValues` runs a Repeater pass before generic field coercion (handles JSON + flat-key bodies, trims trailing untouched rows, recurses into nested Repeaters). `validateSchema` recurses; per-row errors keyed `items.<i>.<name>`; `min/maxItems` under bare key. `applyStateUpdate` resolves dotted paths; row-scoped `$get/$set` + `ctx.row` exposed to `afterStateUpdated`; cross-row reads via dotted paths. Inner `Section.visible(({ values }) => …)` sees row-scoped values. Walkers (`findForms / findActions / findTables / findFieldByName / validation walk / coerce walkFields`) STOP at Repeater boundary via structural `isRepeaterField` helper. Client renderer `react/fields/RepeaterInput.tsx` uses `FormIdContext` for localStorage keying; uncontrolled inputs with name-prefixing per row preserve typed values across reorder/clone/collapse. Reorder via native HTML5 drag-and-drop (grip handle + 2px drop indicator) plus Up/Down buttons as keyboard fallback — both routes through pure helper `reorderRows(rows, fromIdx, insertBeforeIdx)`. Inner-field live re-resolve roundtrip wired via container-level delegated `onChange / onBlur` in `RepeaterInput`: dotted-path `target.name` → `findFieldMeta(formMeta, name)` (now walks Repeater rows) → `formState.triggerLive(name, value)`. `FormStateProvider` snapshots the form's full DOM via `parseFormDataToNested(new FormData(formRef.current))` then writes the override through `writeNestedValue`, so the server sees fresh cross-row values + the just-typed leaf. `useFieldState` returns `controlled: false` for dotted names (preserves uncontrolled-input reorder behavior) but still proxies `triggerLive`. **Plan #14 v1.2 (2026-05-02):** React-controlled primitives that update via callbacks (Switch / Slider / Base UI Select / Checkbox / Radio / DateField / DateTime / Color / KeyValue / FileUpload / CheckboxList) call `fs.triggerLive(value)` explicitly in BOTH controlled and uncontrolled paths so their inner `live()` fires inside Repeater rows. Native inputs (text/number/email/textarea/range/date/checkbox/radio) still bubble through `RepeaterInput`'s container-level delegate as before. **Row-level visibility:** `Repeater.itemHidden(rule)` — boolean or `(LayoutContext) => bool | Promise<bool>`; truthy stamps `RepeaterRowMeta.hidden = true`. The renderer keeps hidden rows mounted via `display: none` (no chrome, no drag wiring) so inputs + `__id` round-trip through FormData on submit — visibility is purely UX, never a data filter. Move Up/Down skips hidden neighbours; throwing predicate fails-closed-as-VISIBLE (inverse of layout `visible()`'s posture — silent hiding of in-progress data is the worse failure mode). `itemHidden` re-evaluates on every server resolve (initial SSR, `live()` re-resolve, full submit re-render); the renderer-side `RepeaterInput` / `BuilderInput` sync `hidden / canDelete / canClone / canReorder` from fresh `meta.rows` by row id via `react/fields/syncRowGates.ts` so locally added rows + uncontrolled-input typed values survive the round-trip. Throwing predicate fails-closed-as-VISIBLE (inverse of layout `visible()`'s posture — silent hiding of in-progress data is the worse failure mode). **Plan #14 follow-up — `BuilderField/Builder` (2026-05-02):** heterogeneous-row sibling. `Block.make(name).label().icon().columns().schema([…]).maxItems(n)` defines block types; `Builder.make(name).blocks([…]).reorderable().cloneable().collapsible().blockNumbers().blockPickerColumns(n).addable(false).deletable(false).reorderableWithButtons().addActionAlignment('start'\|'center'\|'end').itemLabel((data, blockName)=>str).itemHidden(rule)`. Storage envelope: `[{ __id, type, data: {…block fields} }]`. Server-side: `resolveBuilderRows` resolves each row against the block matching `row.type`, ships `meta.rows: { id, type, children, itemLabel?, hidden?, unknownType? }[]` + `meta.blocks: { name, label, icon?, columns?, maxItems?, template }[]` (per-block resolved templates so the picker can mount fresh rows without a roundtrip). `coerceBuilderValue` folds JSON + flat-key bodies into the envelope shape; `validateBuilder` keys per-row errors as `name.<i>.data.<child>`, total-count + per-block-type maxItems land under bare key. `applyBuilderStateUpdate` handles dotted paths `name.<i>.data.<leaf>` (the literal `data` segment distinguishes from Repeater's `name.<i>.<leaf>`) — picks the block from `values[name][i].type`, resolves leaf from block schema, runs `afterStateUpdated` with row-scoped `$get/$set` + `ctx.row.blockType`. Walkers (`findForms / findActions / findTables / findFieldByName / coerce walkFields / validate walk`) stop at Builder via structural `isBuilderField` helper alongside `isRepeaterField`. Unknown block types in submitted data round-trip verbatim (renderer shows a placeholder, server passes data through) — config rollbacks never silently lose content. Client renderer `react/fields/BuilderInput.tsx` reuses `reorderRows` from `RepeaterInput`; the picker dropdown is a plain `useState`-driven menu (no Popover dep) that greys out per-block-type capped options; row header carries block icon (via `useIconFor` from `react/icon-context.tsx`) + optional 1-based numbering; localStorage keying namespaces under `pilotiq.builder.<formId>.<name>.<rowId>` (parallel to repeater). **`Repeater.relationship(name | { name, model?, foreignKey?, orderColumn? })` (2026-05-03):** stores rows in a real `HasMany` relation on the parent record instead of a JSON column. Field surface `.relationship(arg).orderColumn(col)`; mutually exclusive with `simple()` and `dehydrated(false)`. Wire shape `meta.relationship?: { name, orderColumn? }` (server-only `model` / `foreignKey` never serialize). Load: `pageData.applyRelationshipRepeaterFill(form, values, record, R.model)` reads rows from `parent.related(name)` via `resolveRelatedQuery`, stamps `__id = String(child.pk)`, strips PK + FK from each rendered row. Save: `dispatchFormSubmit` calls `extractRelationshipRepeaters` after `coerceFormValues + unwrapSimpleRepeaters` (deletes the field's value from `data` so the parent's `M.update / create` never sees it), then after `persist()` returns the parent record runs `persistRelationshipRows` — diff submitted rows against `parent.related(name)` rows: `__id` matching an existing PK → `M.update(__id, row)` (FK NOT overwritten, defends against tampered re-link), `__id` absent or non-matching → `M.create({ ...row, [foreignKey]: parentPk })`, existing PKs missing from submitted set → `M.delete(pk)`. `orderColumn` (when set) stamps the row's 0-based index on every create + update payload. Routes (`POST /:slug/create`, `POST /:slug/:id/edit`) thread `parentModel: R.model` onto the `FormContext`; the pipeline throws a clear error when missing. ORM contract additions: `getParentRelationDescriptor(parentModel, name)` reads `static relations[name]` from the parent (rudder convention `{ type, model: () => ChildModel, foreignKey }`), returns `undefined` when absent — caller throws with a config message pointing at the override paths. **M2M family shipped 2026-05-05 cont'd⁸** — `belongsToMany`, `morphToMany`, `morphedByMany` all dispatch through `parent[rel]().attach/detach/sync` (resolved via `resolveM2MAccessor` in `src/orm/m2mAccessor.ts`). Row-create → `M.create()` then `accessor.attach([newPk])`. Row-update → `M.update()` (pivot untouched). Row-remove → `accessor.detach([pk])` only — **no `M.delete`** (the related child may be linked to other parents; cascadeDelete deferred). `cfg.orderColumn` rejected with a clear error under M2M (ORM has no `orderByPivot`). New ORM helper `getM2MRelationDescriptor(parentModel, name)` recognizes the three M2M `type` strings; called FIRST in `resolveChildAndAttachment` (a belongsToMany entry has no `foreignKey` so it'd silently fall through to the hasMany branch otherwise). Plan: `docs/plans/repeater-relationship-m2m.md`. Remaining gaps: pivot-extras editing (ORM v1 doesn't surface pivot reads), `cascadeDelete: true` opt-in. No transaction wrapper around parent + child diff in v1 — partial failure leaves the parent saved. Plan + memory: `docs/plans/repeater-relationship.md`, `docs/guide/repeater.md` "Relationship-backed rows" section, `project_pilotiq_repeater_relationship.md`. **`Builder.relationship(name | { name, model?, foreignKey?, typeColumn?, dataColumn?, orderColumn? })` (2026-05-05 cont'd³):** heterogeneous-row sibling. Each row persists as a child record carrying a discriminator column (default `'type'`, holds the block name) + a JSON payload column (default `'data'`, holds the per-block inner-schema values verbatim) — column names overridable via `typeColumn` / `dataColumn`. Field surface `.relationship(arg).orderColumn(col)`; mutually exclusive with `dehydrated(false)`. Wire shape `meta.relationship?: { name, typeColumn?, dataColumn?, orderColumn? }` (server-only `model` / `foreignKey` never serialize). Load: `pageData.applyRelationshipBuilderFill(form, values, record, R.model)` runs after `applyRelationshipRepeaterFill` in `resourceEditData`; reads rows from `parent.related(name)`, stamps `{__id, type, data}` per row, JSON-parses string `data` columns, strips PK + FK + type/data from each rendered row payload. Save: `dispatchFormSubmit` runs `extractRelationshipBuilders` after the Repeater extract (deletes the field's value from `data`), then after `persist()` returns runs `persistRelationshipBuilderRows` — diff submitted rows: `__id` matching an existing PK → `M.update(__id, { [typeColumn]: row.type, [dataColumn]: row.data, [orderColumn]: idx })` (FK NOT overwritten); `__id` absent or non-matching → `M.create({ [typeColumn]: row.type, [dataColumn]: row.data, [foreignKey]: parentPk, [orderColumn]: idx })`; existing PKs missing from submitted set → `M.delete(pk)`. Type column rewrites on update — block type can switch between submits. Reuses Repeater's existing routes-side `parentModel: R.model` threading + `getParentRelationDescriptor` ORM helper. v1 = `hasMany` + `morphMany` / `morphOne` only; **M2M family deliberately deferred** (heterogeneous `{type, data}` envelope doesn't compose with pivot semantics — `resolveBuilderChildAndAttachment` raises a clear error pointing at `Repeater.relationship`). Per-block-type model dispatch (each block points at a different child model) is the prerequisite for ever supporting M2M on Builder; deferred until a consumer asks. Plan + guide: `docs/plans/builder-relationship.md`, `docs/guide/builder.md` "Relationship-backed rows" section, `project_pilotiq_builder_relationship.md`.
|
|
83
|
+
- `src/fields/` — `Field` base + 20 subclasses (`TextField, EmailField, NumberField, SelectField, TextareaField, ToggleField, DateField, SlugField`, **Plan #6:** `HiddenField/Hidden, CheckboxField/Checkbox, RadioField/Radio, CheckboxListField/CheckboxList, SliderField/Slider, ColorPickerField/ColorPicker, DateTimePickerField/DateTimePicker, KeyValueField/KeyValue, FileUploadField/FileUpload`, **Plan #14:** `RepeaterField/Repeater`, **Tier-2 micro-plans (2026-05-04):** `ToggleButtonsField/ToggleButtons` — sugar over Radio with chip rendering; same `OptionsResolver` shape; no separate coerce branch (string passthrough). `TagsInputField/TagsInput` — free-text tag chips; `string[]` value; `.suggestions(string[]|resolver) / .separator(',') / .splitKeys(['Enter']) / .reorderable() / .maxTags(n)`; wire format = JSON-encoded array in a single hidden input; new `tagsInput` coerce branch parses back to `string[]`. **`reorderable()` (2026-05-03):** chips become draggable via native HTML5 drag-and-drop with a 2px vertical drop indicator and a grip-icon affordance; reuses `reorderRows` helper from `RepeaterInput`. Off by default — most tag sets are insertion-ordered or alphabetized. **`MarkdownField/Markdown` (2026-05-04 cont'd)** — plain-markdown editor; raw string value (same wire format as `TextareaField`, no new coerce branch); `.toolbarButtons([…]) / .disableToolbarButtons([…]) / .minHeight(css) / .maxHeight(css) / .fileAttachmentsDirectory(d) / .fileAttachmentsVisibility('public'\|'private')`. Default toolbar = 10 buttons (`bold/italic/strike/link/heading/bulletList/orderedList/blockquote/codeBlock/attachFiles`). Renderer ships a tab switcher (Write / Preview); preview HTML is rendered client-side via `marked` (`gfm: true, breaks: false`), no DOMPurify in v1 (admin-trusted authors). `attachFiles` reuses the existing `_uploads` route + `UploadAdapter`; the button is stripped server-side when no adapter is registered via the new `RenderContext.hasUploadAdapter` flag (see "RenderContext" note below). Paste-image splices ``; ⌘B/⌘I/⌘K shortcuts). Visibility flags + condition callbacks (`showWhen, hideWhen, disabledWhen`), validators via `.validate(v|v[])`. **Plan #5:** `Field.live(opts?: boolean | { onBlur?: boolean; debounce?: number })` marks re-resolve trigger; `Field.afterStateUpdated((value, ctx) => …)` server hook; `SelectField.options(fnOrArray)` async-aware; `FieldCondition` widened from `(record) => bool` to `(ctx: ConditionContext) => bool`. Conditions skip when both `record` and `values` are undefined. **`Field.afterStateUpdatedJs(body)` (2026-05-04 cont'd, Tier-2 follow-up):** client-only counterpart to `afterStateUpdated`. Body string compiled via `new Function` (CSP `unsafe-eval` required) with `$state / $get / $set` bound; cached by source-string identity in `react/fieldJsHandler.ts`; runs synchronously on every change (no `live()` required, no roundtrip). Compose with the server hook — JS runs first, server response (when `live()` is also set) overlays sibling values. Repeater/Builder rows: dotted-path `$get / $set` route through `readNestedValue / writeNestedValue` (snapshot-then-overlay so `$get(thisField)` matches `$state`). `tagFormStateUrls` stamps `stateUrl` for forms with EITHER `live()` OR `afterStateUpdatedJs` so the `FormStateProvider` mounts (the endpoint is unused for JS-only forms; client only POSTs on `live`). **Plan #6 cross-field plumbing on `Field`:** `prefix(string|{icon}) / suffix(...) / helperText(text) / inlineLabel(v=true) / default(value) / dehydrated(false) / formatStateUsing(fn)`. **`inlineLabel()` (2026-05-04 cont'd)** mirrors the `Entry.inlineLabel` shipped with Plan #16 — `FieldShell` swaps to a `flex items-baseline gap-3` row with a `min-w-32` label column (default label-above unchanged); helperText still renders under the value. Bare `inlineLabel(false)` clears. `dehydrated(false)` drops the field from the POST body before validation. `OptionsResolver` extracted to `fields/optionsResolver.ts` and shared by SelectField/Radio/CheckboxList. FileUpload reads `ctx.uploadUrl` (panel-level URL stamped by `pageData.uploadCtx`). New coerce branches: `checkbox` (toggle-like), `slider` (number-like), `dateTime`, `checkboxList` (string[]), `color`, `keyValue` (JSON-string → object), `fileUpload` (URL string or string[]). **Plan #14 `RepeaterField`:** array-of-subschema field; `.schema([...]) / .columns(n) / .defaultItems(n) / .min/maxItems / .reorderable() / .collapsible().collapsed() / .accordion() / .cloneable() / .itemLabel(row=>str) / .addActionLabel(text)`. **`accordion()` (2026-05-06):** one-row-open-at-a-time mode; auto-arms `collapsible()`. Renderer swaps the per-row `collapsed[id]` map for a single `accordionOpenId: string | null` slot; persisted under `pilotiq.repeater.<formId>.<name>.accordion`. Compose with `collapsed()` for "all start closed" (default opens first visible row). Available on Builder too — same shape, persisted under `pilotiq.builder.<formId>.<name>.accordion`. **`expandAction(b) / expandAllAction(b?) / collapseAllAction(b?)` (2026-05-08, audit gap #7):** widens `RowButtonKind` from 7 → 10 slots. `expandAction` is a sibling of `collapseAction` for the *collapsed* state only (open state still routes through `collapseAction`; bare `collapseAction` continues to cover both states for back-compat). `expandAllAction / collapseAllAction` are opt-in field-header bulk chips — calling enables (with or without a `RowButton` override), auto-arms `collapsible()`. Renderer mounts via shared `<BulkCollapseHeader>` above the rows in both Repeater and Builder; accordion mode preserves "only one open" by opening the first visible row on `expandAll` and clearing `accordionOpenId` on `collapseAll`. Per-row mode iterates every row id and writes the `pilotiq.repeater|builder.<formId>.<name>.<rowId>` storage slot so reload restores the bulk state. Table mode skips the chrome (collapsing is meaningless on `<tr>` rows). All three serialize through the existing `serializeRowButtons` helper — no new wire-shape branch. Server-resolved `meta.rows: { id, children, itemLabel? }[]` + `meta.template`. `coerceFormValues` runs a Repeater pass before generic field coercion (handles JSON + flat-key bodies, trims trailing untouched rows, recurses into nested Repeaters). `validateSchema` recurses; per-row errors keyed `items.<i>.<name>`; `min/maxItems` under bare key. `applyStateUpdate` resolves dotted paths; row-scoped `$get/$set` + `ctx.row` exposed to `afterStateUpdated`; cross-row reads via dotted paths. Inner `Section.visible(({ values }) => …)` sees row-scoped values. Walkers (`findForms / findActions / findTables / findFieldByName / validation walk / coerce walkFields`) STOP at Repeater boundary via structural `isRepeaterField` helper. Client renderer `react/fields/RepeaterInput.tsx` uses `FormIdContext` for localStorage keying; uncontrolled inputs with name-prefixing per row preserve typed values across reorder/clone/collapse. Reorder via native HTML5 drag-and-drop (grip handle + 2px drop indicator) plus Up/Down buttons as keyboard fallback — both routes through pure helper `reorderRows(rows, fromIdx, insertBeforeIdx)`. Inner-field live re-resolve roundtrip wired via container-level delegated `onChange / onBlur` in `RepeaterInput`: dotted-path `target.name` → `findFieldMeta(formMeta, name)` (now walks Repeater rows) → `formState.triggerLive(name, value)`. `FormStateProvider` snapshots the form's full DOM via `parseFormDataToNested(new FormData(formRef.current))` then writes the override through `writeNestedValue`, so the server sees fresh cross-row values + the just-typed leaf. `useFieldState` returns `controlled: false` for dotted names (preserves uncontrolled-input reorder behavior) but still proxies `triggerLive`. **Plan #14 v1.2 (2026-05-02):** React-controlled primitives that update via callbacks (Switch / Slider / Base UI Select / Checkbox / Radio / DateField / DateTime / Color / KeyValue / FileUpload / CheckboxList) call `fs.triggerLive(value)` explicitly in BOTH controlled and uncontrolled paths so their inner `live()` fires inside Repeater rows. Native inputs (text/number/email/textarea/range/date/checkbox/radio) still bubble through `RepeaterInput`'s container-level delegate as before. **Row-level visibility:** `Repeater.itemHidden(rule)` — boolean or `(LayoutContext) => bool | Promise<bool>`; truthy stamps `RepeaterRowMeta.hidden = true`. The renderer keeps hidden rows mounted via `display: none` (no chrome, no drag wiring) so inputs + `__id` round-trip through FormData on submit — visibility is purely UX, never a data filter. Move Up/Down skips hidden neighbours; throwing predicate fails-closed-as-VISIBLE (inverse of layout `visible()`'s posture — silent hiding of in-progress data is the worse failure mode). `itemHidden` re-evaluates on every server resolve (initial SSR, `live()` re-resolve, full submit re-render); the renderer-side `RepeaterInput` / `BuilderInput` sync `hidden / canDelete / canClone / canReorder` from fresh `meta.rows` by row id via `react/fields/syncRowGates.ts` so locally added rows + uncontrolled-input typed values survive the round-trip. Throwing predicate fails-closed-as-VISIBLE (inverse of layout `visible()`'s posture — silent hiding of in-progress data is the worse failure mode). **Plan #14 follow-up — `BuilderField/Builder` (2026-05-02):** heterogeneous-row sibling. `Block.make(name).label().icon().columns().schema([…]).maxItems(n)` defines block types; `Builder.make(name).blocks([…]).reorderable().cloneable().collapsible().blockNumbers().blockPickerColumns(n).addable(false).deletable(false).reorderableWithButtons().addActionAlignment('start'\|'center'\|'end').itemLabel((data, blockName)=>str).itemHidden(rule)`. Storage envelope: `[{ __id, type, data: {…block fields} }]`. Server-side: `resolveBuilderRows` resolves each row against the block matching `row.type`, ships `meta.rows: { id, type, children, itemLabel?, hidden?, unknownType? }[]` + `meta.blocks: { name, label, icon?, columns?, maxItems?, template }[]` (per-block resolved templates so the picker can mount fresh rows without a roundtrip). `coerceBuilderValue` folds JSON + flat-key bodies into the envelope shape; `validateBuilder` keys per-row errors as `name.<i>.data.<child>`, total-count + per-block-type maxItems land under bare key. `applyBuilderStateUpdate` handles dotted paths `name.<i>.data.<leaf>` (the literal `data` segment distinguishes from Repeater's `name.<i>.<leaf>`) — picks the block from `values[name][i].type`, resolves leaf from block schema, runs `afterStateUpdated` with row-scoped `$get/$set` + `ctx.row.blockType`. Walkers (`findForms / findActions / findTables / findFieldByName / coerce walkFields / validate walk`) stop at Builder via structural `isBuilderField` helper alongside `isRepeaterField`. Unknown block types in submitted data round-trip verbatim (renderer shows a placeholder, server passes data through) — config rollbacks never silently lose content. Client renderer `react/fields/BuilderInput.tsx` reuses `reorderRows` from `RepeaterInput`; the picker dropdown is a plain `useState`-driven menu (no Popover dep) that greys out per-block-type capped options; row header carries block icon (via `useIconFor` from `react/icon-context.tsx`) + optional 1-based numbering; localStorage keying namespaces under `pilotiq.builder.<formId>.<name>.<rowId>` (parallel to repeater). **`Repeater.relationship(name | { name, model?, foreignKey?, orderColumn? })` (2026-05-03):** stores rows in a real `HasMany` relation on the parent record instead of a JSON column. Field surface `.relationship(arg).orderColumn(col)`; mutually exclusive with `simple()` and `dehydrated(false)`. Wire shape `meta.relationship?: { name, orderColumn? }` (server-only `model` / `foreignKey` never serialize). Load: `pageData.applyRelationshipRepeaterFill(form, values, record, R.model)` reads rows from `parent.related(name)` via `resolveRelatedQuery`, stamps `__id = String(child.pk)`, strips PK + FK from each rendered row. Save: `dispatchFormSubmit` calls `extractRelationshipRepeaters` after `coerceFormValues + unwrapSimpleRepeaters` (deletes the field's value from `data` so the parent's `M.update / create` never sees it), then after `persist()` returns the parent record runs `persistRelationshipRows` — diff submitted rows against `parent.related(name)` rows: `__id` matching an existing PK → `M.update(__id, row)` (FK NOT overwritten, defends against tampered re-link), `__id` absent or non-matching → `M.create({ ...row, [foreignKey]: parentPk })`, existing PKs missing from submitted set → `M.delete(pk)`. `orderColumn` (when set) stamps the row's 0-based index on every create + update payload. Routes (`POST /:slug/create`, `POST /:slug/:id/edit`) thread `parentModel: R.model` onto the `FormContext`; the pipeline throws a clear error when missing. ORM contract additions: `getParentRelationDescriptor(parentModel, name)` reads `static relations[name]` from the parent (rudder convention `{ type, model: () => ChildModel, foreignKey }`), returns `undefined` when absent — caller throws with a config message pointing at the override paths. **M2M family shipped 2026-05-05 cont'd⁸** — `belongsToMany`, `morphToMany`, `morphedByMany` all dispatch through `parent[rel]().attach/detach/sync` (resolved via `resolveM2MAccessor` in `src/orm/m2mAccessor.ts`). Row-create → `M.create()` then `accessor.attach([newPk])`. Row-update → `M.update()` (pivot untouched). Row-remove → `accessor.detach([pk])` only — **no `M.delete`** (the related child may be linked to other parents; cascadeDelete deferred). `cfg.orderColumn` rejected with a clear error under M2M (ORM has no `orderByPivot`). New ORM helper `getM2MRelationDescriptor(parentModel, name)` recognizes the three M2M `type` strings; called FIRST in `resolveChildAndAttachment` (a belongsToMany entry has no `foreignKey` so it'd silently fall through to the hasMany branch otherwise). Plan: `docs/plans/repeater-relationship-m2m.md`. Remaining gaps: pivot-extras editing (ORM v1 doesn't surface pivot reads), `cascadeDelete: true` opt-in. No transaction wrapper around parent + child diff in v1 — partial failure leaves the parent saved. Plan + memory: `docs/plans/repeater-relationship.md`, `docs/guide/repeater.md` "Relationship-backed rows" section, `project_pilotiq_repeater_relationship.md`. **`Builder.relationship(name | { name, model?, foreignKey?, typeColumn?, dataColumn?, orderColumn? })` (2026-05-05 cont'd³):** heterogeneous-row sibling. Each row persists as a child record carrying a discriminator column (default `'type'`, holds the block name) + a JSON payload column (default `'data'`, holds the per-block inner-schema values verbatim) — column names overridable via `typeColumn` / `dataColumn`. Field surface `.relationship(arg).orderColumn(col)`; mutually exclusive with `dehydrated(false)`. Wire shape `meta.relationship?: { name, typeColumn?, dataColumn?, orderColumn? }` (server-only `model` / `foreignKey` never serialize). Load: `pageData.applyRelationshipBuilderFill(form, values, record, R.model)` runs after `applyRelationshipRepeaterFill` in `resourceEditData`; reads rows from `parent.related(name)`, stamps `{__id, type, data}` per row, JSON-parses string `data` columns, strips PK + FK + type/data from each rendered row payload. Save: `dispatchFormSubmit` runs `extractRelationshipBuilders` after the Repeater extract (deletes the field's value from `data`), then after `persist()` returns runs `persistRelationshipBuilderRows` — diff submitted rows: `__id` matching an existing PK → `M.update(__id, { [typeColumn]: row.type, [dataColumn]: row.data, [orderColumn]: idx })` (FK NOT overwritten); `__id` absent or non-matching → `M.create({ [typeColumn]: row.type, [dataColumn]: row.data, [foreignKey]: parentPk, [orderColumn]: idx })`; existing PKs missing from submitted set → `M.delete(pk)`. Type column rewrites on update — block type can switch between submits. Reuses Repeater's existing routes-side `parentModel: R.model` threading + `getParentRelationDescriptor` ORM helper. v1 = `hasMany` + `morphMany` / `morphOne` only; **M2M family deliberately deferred** (heterogeneous `{type, data}` envelope doesn't compose with pivot semantics — `resolveBuilderChildAndAttachment` raises a clear error pointing at `Repeater.relationship`). Per-block-type model dispatch (each block points at a different child model) is the prerequisite for ever supporting M2M on Builder; deferred until a consumer asks. Plan + guide: `docs/plans/builder-relationship.md`, `docs/guide/builder.md` "Relationship-backed rows" section, `project_pilotiq_builder_relationship.md`. **`Repeater.afterCreate(fn) / afterUpdate(fn) / afterDelete(fn)` (2026-05-10 cont'd⁷):** per-row hooks fired inside `persistRelationshipRows` after each child operation. Handler receives `(record, ctx: RepeaterRowContext)` with `ctx = { parent, parentId, field, index, mode }`; `mode` is the resolved `RepeaterRelationMode` (`'hasMany' | 'morphMany' | 'belongsToMany' | 'morphToMany' | 'morphedByMany'`) so handlers can branch on M2M-detach-vs-physical-delete in `afterDelete`. `index` is `-1` on `afterDelete` (deleted rows aren't in the submitted set). Each setter throws at config time when `relationship()` hasn't been called first (config-time guard mirrors `orderColumn() / pivotColumns()`). Errors propagate — a throwing handler stops the rest of the persist diff; v1 isn't transactional so earlier rows are already committed. `afterUpdate` payload falls back to `{ ...existingByPk, ...payload }` when `model.update` returns void (rudder ORM's update typing — kept for ORMs that don't echo the updated record).
|
|
83
84
|
- `src/entries/` — **Plan #16 (2026-05-04 cont'd)** read-only label-value pairs for `Resource.detail()`. **`RepeatableEntry` (2026-05-06 cont'd⁶)** — array-of-subschema sibling of `RepeaterField`. `RepeatableEntry.make(name).schema([Entry…]).columns(n).grid(n).table([cols]).contained(false)`. Reads the array off `ctx.record[name]` and resolves the inner schema once per row with `record` scoped to the row's data — inner entries (`TextEntry / BadgeEntry / IconEntry / ImageEntry / KeyValueEntry / ColorEntry`) read state via the same `record[childName]` lookup they use anywhere else. Three layout modes (renderer dispatches `table > grid > stack`); v1 takes a fixed integer for `grid()` (responsive object form deferred until asked). Primitive array elements stash under a reserved `_value` key so a `TextEntry.make('_value')` can target them. Empty / non-array / null falls through to the inherited `default()` placeholder. Resolution lives in `resolveSchema.ts → resolveRepeatableRows` next to the Repeater/Builder branches. `Entry` abstract base extends `Element` with the chrome surface (`label / inlineLabel / default / helperText / tooltip / weight / color / size / lineClamp / wrap / copyable / formatStateUsing`) plus the `Column`-mirroring formatter chain (`since / dateTime / money / numeric / limit`). Subclasses set `getEntryType()` for the wire-side discriminator. Seven leaves: `TextEntry` (default), `BadgeEntry.colors({ value: BadgeColor })`, `IconEntry.options({ value: { icon, color, label } })`, `ImageEntry.dimensions(px) / .square() / .rounded() / .circle() / .width(px) / .height(px)`, **`KeyValueEntry.keyLabel(t).valueLabel(t)` (2026-05-04 cont'd)** — read-only sibling of `KeyValueField`; renderer normalizes object | JSON-string | other into a `Record<string, unknown>` (non-JSON strings + arrays fall through to fallback) and renders a two-column kv table; nested values JSON-stringify for compactness; copyable serializes objects via `JSON.stringify`, **`ColorEntry.dimensions(px) / .square / .rounded / .circle / .hideValue()` (2026-05-04 cont'd)** — sibling of `ColorPickerField`; renders the raw CSS color string as a chip + the value text beside (toggle with `hideValue()` for chip-only). State resolves from `ctx.record[name]` at meta-build time — `Entry.toMeta(ctx)` is gated through the `el instanceof Field || el instanceof Filter || el instanceof Entry` branch in `resolveSchema.ts`. **`Entry.state(path | fn)` (2026-05-04 cont'd⁵):** override the default lookup when the value lives at a nested path or needs to be derived. String form does dotted-path traversal (`'author.name'`, `'tags.0.label'`); numeric segments index into arrays; missing intermediates resolve to `undefined`. Function form runs the user accessor with the full record; throwing fails soft (value=undefined). The entry's `name` still drives the auto-derived label and the discriminator key — pair `.state(...)` with `.label(...)` when the path doesn't read well as a heading. Composes with `formatStateUsing` (state resolves the value, formatter formats it). **`ComponentEntry` (2026-05-04 cont'd⁶, escape-hatch leaf):** hands rendering off to a user-supplied React component registered via `registerEntryComponents({ Name: Component })` from the `@pilotiq/pilotiq/entries` subpath (parallel to `@pilotiq/pilotiq/widgets` for `View`). Subclass form sets `static componentName = '...'`; fluent form uses `.component('...')`. Component receives `{ value }` props (where `value` is the resolved state via `.state(...)` or `record[name]`). For multi-field needs, pack via `.state(r => ({ … }))`. `entryType: 'component'`; renderer dispatches inside `renderEntry` and paints inline error panels (`<EntryComponentError>`) for missing-name / missing-registration. Render-time errors propagate to React's nearest error boundary (no per-entry boundary in v1). The renderer wraps the user component in `<EntryShell>` for label / helperText / tooltip / copyable parity with the typed leaves. Subpath `@pilotiq/pilotiq/entries` lives next to `/widgets` + `/uploads` for the same client-safe-import reason. Demo: `playground/app/Pilotiq/Posts/{ReadingStats.tsx, PostResource.detail()}` + registration in `pages/+Layout.tsx`. `formatStateUsing` runs server-side and stamps `_formatted` (renderer prefers it over re-applying `format`); throwing handlers fail soft. Renderer `react/SchemaRenderer.tsx → renderEntry` dispatches on `meta.entryType` (`'text' | 'badge' | 'icon' | 'image' | 'keyValue' | 'color'`) and wraps every leaf in `<EntryShell>` (label-above by default, label-left when `inlineLabel()`; copyable trigger and `?` info-tooltip both live in the shell). Wire-side `EntryMeta.type === 'entry'` so walkers branch via `isEntry(el)` rather than `instanceof`. Layout-level `visible / hidden / columnSpan` inherited from `Element`. Plan: `docs/plans/infolist-entries.md`, guide `docs/guide/infolists.md`. Demos: `playground/app/Pilotiq/Posts/PostResource.detail()` (Text / Badge / Icon), `playground/app/Pilotiq/Articles/ArticleResource.detail()` (KeyValue / Color against the `metadata` JSON-blob and `accentColor` columns).
|
|
84
85
|
- `src/filters/` — `Filter` base + `SelectFilter / MultiSelectFilter / BooleanFilter / TernaryFilter / DateRangeFilter / TrashedFilter / FormFilter / QueryBuilderFilter`. Lives as children of `Table` via `.filters([...])`. URL keys; reserved keys are `search/sort/page/perPage`. `Filter.query(fn)` overrides default where-clause. **Filter expansion (2026-05-03):** `TernaryFilter` is 3-state (yes/no/blank) for nullable booleans — `.trueLabel/.falseLabel/.blankLabel/.nullable(false)`; default `_queryFn` set in `make()` emits `where(true)/where(false)/whereNull(name)` (falls back to `where(name,null)` when `whereNull?` is missing on the query — added as optional to `ModelQuery` parallel to Plan #13's `withTrashed?`). `DateRangeFilter` is a single URL key with `from..to`-encoded value (`?createdAt=2026-01-01..2026-12-31`, either side may be empty); `.includesTime/.minDate/.maxDate`; default handler emits `where(>=,from)`/`where(<=,to)` skipping the empty side; `parseDateRangeValue` / `encodeDateRangeValue` exported. Both filters set `_queryFn` inside `make()` (TrashedFilter pattern, NOT BooleanFilter's kind-branch pattern), so the model adapter's existing `if (customQuery)` branch covers them with no kind-specific changes. Renderer: `'ternary'` reuses `FilterSelect` with server-supplied options; `'dateRange'` is a new `FilterDateRange` component (two date / datetime-local inputs + Clear `×`, SPA-nav, `?page` reset on change). **Batch C (2026-05-02):** `Filter.indicator(string | (value, filter) => string)` overrides the active-filter pill text; default is `"<label>: <displayValue>"` where `displayValue` comes from each subclass's `formatActiveValue(value)` hook (Select/Multi → option labels, Boolean → Yes/No, Ternary → configured trueLabel/falseLabel/blankLabel, DateRange → `from → to` / `≥ from` / `≤ to`). `toMeta()` emits `indicator?: string` only when the filter has an active value. New `MultiSelectFilter` is a sibling of SelectFilter — `.options([...])`, comma-separated URL value (`?status=draft,published`), `kind: 'multiSelect'`, default `_queryFn` set in `make()` emits `where(name, 'IN', values)` (skips when the parsed list is empty). Helpers `parseMultiSelectValue / encodeMultiSelectValue` exported alongside the class. Renderer: new `<ActiveFiltersBar>` pill row above the table (× clears the URL key + resets `?page`; "Clear all" appears with 2+ active pills); new `FilterMultiSelect` checkbox stack inside the popover for `kind === 'multiSelect'`. **FormFilter (2026-05-04):** arbitrary-schema multi-field filter — `FormFilter.make(name).form([fields…]).handle((q, values) => q).formIndicator((values, filter) => string)`. URL value is JSON-encoded under the single filter key (`?amount={"min":100,"max":500}`); `parseFormFilterValue / encodeFormFilterValue` helpers exported. `toMeta(ctx)` is async, calls `resolveSchema(form, ctx)` to resolve inner fields (so dependent-options resolvers see the user / values context just like a regular form), then walks the resolved tree and stamps each field's `defaultValue` from the parsed URL payload so existing filters round-trip into the popover. `Filter.toMeta` widened to `(ctx?: RenderContext): FilterMeta | Promise<FilterMeta>` and `protected buildBaseMeta()` extracted so sibling sync subclasses (Select/Boolean/Ternary/DateRange/MultiSelect/Trashed) keep `super.toMeta()`-equivalent shape without spreading a Promise union. `resolveSchema` now passes `ctx` to `Filter` instances (mirroring the Field branch) so `FormFilter`'s inner schema resolves with the surrounding render context. `Filter.toMeta` default queryFn for `FormFilter` is a no-op `(q) => q` so modelDefaults' `if (customQuery)` short-circuits cleanly when the user hasn't called `.handle()` (otherwise the default `where(name, jsonString)` clause would fire with a JSON blob). Renderer: `kind === 'form'` mounts a `<FilterForm>` inside the existing `FilterPopover` — `<form>` ref + `new FormData(form)` collector + `encodeFormFilterValue` + Apply / Clear submit buttons. Field renderers reuse `renderFormChild` so every existing field type works inside a filter form (the popover is a small surface, so plain fields read best). **QueryBuilderFilter (2026-05-05 cont'd²¹):** Filament-style composable advanced filter — `QueryBuilderFilter.make(name).label().constraints([Constraint…])`. Constraints are typed value-objects (NOT Elements) — `TextConstraint / NumberConstraint / DateConstraint / SelectConstraint / BooleanConstraint`. Each declares `getOperators()` (per-operator label + `valueKind`) and `apply(query, operator, value): ModelQuery` (translates a single rule to ORM `where` clauses). URL value JSON-encodes into a single key `?runtime={"operator":"and","rules":[…]}`; tree-walker `applyTreeToQuery` chains every rule via `.where()` (AND-root only — see below). Indicator pill formats as `"Label: N condition(s)"` by default; `.treeIndicator(fn)` for override; `.handle((q, tree, filter) => …)` for custom dispatch (cross-table joins). Renderer `<FilterQueryBuilder>` widens `FilterPopover` to `w-[36rem]` when present; mounts a row-stack of (constraint Select + operator Select + value input dispatched off `valueKind`); local-state until Apply (mirrors FilterForm). v1 = AND-only / no nested groups / no relation traversal. **OR + nested groups blocked on rudder ORM `whereGroup` support** — see `~/Projects/rudder/docs/plans/where-group.md`. `notContains` operator on `TextConstraint` deferred (Prisma adapter doesn't translate `NOT LIKE`). Helpers `parseQueryBuilderValue / encodeQueryBuilderValue / emptyQueryBuilderTree / applyTreeToQuery` exported alongside the filter. Plan + guide: `docs/guide/query-builder.md`.
|
|
85
86
|
- `src/actions/` — `Action` primitive. Placement: `inline | bulk | row | header`. Four mutually-exclusive dispatch modes: `Action.href(url) / .method(m).action(url) / .handler(ctx=>…) / .submit()`. Submit can target outside form via `.form(formId)` (HTML `form=` attribute). Submit can also attach a `name`/`value` pair via `.formField(name, value='1')` so the clicked button's pair lands in the form body — `FormRenderer.onSubmit` threads `event.submitter` into `new FormData(form, submitter)` to preserve it. Confirm-gated submits intentionally don't honor `formField` (programmatic `requestSubmit()` has no submitter). Handler actions get `dispatchUrl` stamped at render time.
|
package/dist/Column.d.ts
CHANGED
|
@@ -70,6 +70,13 @@ export type FormatStateHandler = (value: unknown, record: Record<string, unknown
|
|
|
70
70
|
* on this column's cell, or `undefined` to skip linking that row. Runs
|
|
71
71
|
* server-side inside `loadTableRecords`. */
|
|
72
72
|
export type ColumnRecordUrlHandler = (record: Record<string, unknown>) => string | undefined;
|
|
73
|
+
/** Configuration for `Column.toggleable(...)`. The user can show / hide the
|
|
74
|
+
* column from a per-table dropdown; preference persists to localStorage so
|
|
75
|
+
* it survives reloads + SPA navs. `initiallyHidden` flips the default state
|
|
76
|
+
* so the column starts off-screen and the user opts in. */
|
|
77
|
+
export interface ColumnToggleableConfig {
|
|
78
|
+
initiallyHidden?: boolean;
|
|
79
|
+
}
|
|
73
80
|
export interface ColumnMeta extends ElementMeta {
|
|
74
81
|
type: 'column';
|
|
75
82
|
name: string;
|
|
@@ -94,6 +101,12 @@ export interface ColumnMeta extends ElementMeta {
|
|
|
94
101
|
* computed values for each summarizer land on the table meta under
|
|
95
102
|
* `summaries[columnName]` (`SummaryResult[]`), not on the column. */
|
|
96
103
|
summaries?: SummarizerMeta[];
|
|
104
|
+
/** True when the user can show / hide this column from the toolbar's
|
|
105
|
+
* "Columns" dropdown. `initiallyHidden` flips the default state so
|
|
106
|
+
* the column starts off until the user opts in. */
|
|
107
|
+
toggleable?: {
|
|
108
|
+
initiallyHidden?: true;
|
|
109
|
+
};
|
|
97
110
|
/** Render array values one-per-line (each item separated by `<br>`).
|
|
98
111
|
* Composes with `bulleted()` — when both are set, `bulleted()` wins
|
|
99
112
|
* and the renderer mounts a `<ul>` with bullet markers instead. */
|
|
@@ -188,6 +201,7 @@ export declare class Column extends Element {
|
|
|
188
201
|
protected _copyMessage?: string;
|
|
189
202
|
protected _richText?: ColumnRichTextKind;
|
|
190
203
|
protected _sanitize: boolean | SanitizeConfig;
|
|
204
|
+
protected _toggleable: false | ColumnToggleableConfig;
|
|
191
205
|
protected _required: boolean;
|
|
192
206
|
protected _validators: Validator[];
|
|
193
207
|
protected _confirm?: string;
|
|
@@ -200,6 +214,27 @@ export declare class Column extends Element {
|
|
|
200
214
|
label(l: string): this;
|
|
201
215
|
sortable(v?: boolean): this;
|
|
202
216
|
searchable(v?: boolean): this;
|
|
217
|
+
/**
|
|
218
|
+
* Let the user show / hide this column from the table toolbar's
|
|
219
|
+
* "Columns" dropdown. Preference persists per-table to localStorage
|
|
220
|
+
* under `pilotiq.table.<currentPath>.columns.<col>` so the choice
|
|
221
|
+
* sticks across reloads + SPA navigations.
|
|
222
|
+
*
|
|
223
|
+
* Pass `{ initiallyHidden: true }` to start the column off-screen —
|
|
224
|
+
* useful for technical / debug columns the user opts into.
|
|
225
|
+
*
|
|
226
|
+
* Column.make('email').toggleable()
|
|
227
|
+
* Column.make('internalId').toggleable({ initiallyHidden: true })
|
|
228
|
+
* Column.make('name').toggleable(false) // explicit opt-out
|
|
229
|
+
*
|
|
230
|
+
* Any non-toggleable column always renders. Hidden state is purely
|
|
231
|
+
* presentational — the column's data still loads from the server (so
|
|
232
|
+
* sorts / filters that reference it keep working, and a re-toggle
|
|
233
|
+
* shows fresh values without a roundtrip).
|
|
234
|
+
*/
|
|
235
|
+
toggleable(opts?: boolean | ColumnToggleableConfig): this;
|
|
236
|
+
isToggleable(): boolean;
|
|
237
|
+
getToggleableConfig(): ColumnToggleableConfig | undefined;
|
|
203
238
|
alignment(a: ColumnAlignment): this;
|
|
204
239
|
width(w: string): this;
|
|
205
240
|
/** Fallback string when the cell value is null / undefined / empty. */
|
package/dist/Column.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Column.d.ts","sourceRoot":"","sources":["../src/Column.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Column.d.ts","sourceRoot":"","sources":["../src/Column.ts"],"names":[],"mappings":"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"}
|
package/dist/Column.js
CHANGED
|
@@ -41,6 +41,10 @@ export class Column extends Element {
|
|
|
41
41
|
// server-renders the cell + stamps `_formatted[name] / _richtextCells[name]`.
|
|
42
42
|
_richText;
|
|
43
43
|
_sanitize = true;
|
|
44
|
+
// User-toggleable column visibility — `Table.toggleColumns()` opt-in
|
|
45
|
+
// chrome reads this and stamps the toolbar dropdown. State persists
|
|
46
|
+
// per-table to localStorage so the user's choice sticks across loads.
|
|
47
|
+
_toggleable = false;
|
|
44
48
|
// ─── Editable cell columns (TextInput / Toggle / Select) ───
|
|
45
49
|
// Per-cell PATCH validators — same shape as Field validators. Only
|
|
46
50
|
// consulted when the column is editable (the route handler reads
|
|
@@ -63,6 +67,40 @@ export class Column extends Element {
|
|
|
63
67
|
label(l) { this._label = l; return this; }
|
|
64
68
|
sortable(v = true) { this._sortable = v; return this; }
|
|
65
69
|
searchable(v = true) { this._searchable = v; return this; }
|
|
70
|
+
/**
|
|
71
|
+
* Let the user show / hide this column from the table toolbar's
|
|
72
|
+
* "Columns" dropdown. Preference persists per-table to localStorage
|
|
73
|
+
* under `pilotiq.table.<currentPath>.columns.<col>` so the choice
|
|
74
|
+
* sticks across reloads + SPA navigations.
|
|
75
|
+
*
|
|
76
|
+
* Pass `{ initiallyHidden: true }` to start the column off-screen —
|
|
77
|
+
* useful for technical / debug columns the user opts into.
|
|
78
|
+
*
|
|
79
|
+
* Column.make('email').toggleable()
|
|
80
|
+
* Column.make('internalId').toggleable({ initiallyHidden: true })
|
|
81
|
+
* Column.make('name').toggleable(false) // explicit opt-out
|
|
82
|
+
*
|
|
83
|
+
* Any non-toggleable column always renders. Hidden state is purely
|
|
84
|
+
* presentational — the column's data still loads from the server (so
|
|
85
|
+
* sorts / filters that reference it keep working, and a re-toggle
|
|
86
|
+
* shows fresh values without a roundtrip).
|
|
87
|
+
*/
|
|
88
|
+
toggleable(opts = true) {
|
|
89
|
+
if (opts === false) {
|
|
90
|
+
this._toggleable = false;
|
|
91
|
+
}
|
|
92
|
+
else if (opts === true) {
|
|
93
|
+
this._toggleable = {};
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
this._toggleable = { ...opts };
|
|
97
|
+
}
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
isToggleable() { return this._toggleable !== false; }
|
|
101
|
+
getToggleableConfig() {
|
|
102
|
+
return this._toggleable === false ? undefined : this._toggleable;
|
|
103
|
+
}
|
|
66
104
|
// ─── Layout ───────────────────────────────────────────
|
|
67
105
|
alignment(a) { this._alignment = a; return this; }
|
|
68
106
|
width(w) { this._width = w; return this; }
|
|
@@ -424,6 +462,9 @@ export class Column extends Element {
|
|
|
424
462
|
meta.hasFormatter = true;
|
|
425
463
|
if (this._summarizers.length > 0)
|
|
426
464
|
meta.summaries = this._summarizers.map(s => s.toMeta());
|
|
465
|
+
if (this._toggleable !== false) {
|
|
466
|
+
meta.toggleable = this._toggleable.initiallyHidden ? { initiallyHidden: true } : {};
|
|
467
|
+
}
|
|
427
468
|
if (this._listWithLineBreaks)
|
|
428
469
|
meta.listWithLineBreaks = true;
|
|
429
470
|
if (this._bulleted)
|
package/dist/Column.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Column.js","sourceRoot":"","sources":["../src/Column.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Column.js","sourceRoot":"","sources":["../src/Column.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAoB,MAAM,qBAAqB,CAAA;AA4L/D;;;;;;GAMG;AACH,MAAM,OAAO,MAAO,SAAQ,OAAO;IACxB,IAAI,CAAQ;IACX,MAAM,CAAS;IACf,SAAS,GAAG,KAAK,CAAA;IACjB,WAAW,GAAG,KAAK,CAAA;IAE7B,kBAAkB;IACR,WAAW,GAAe,MAAM,CAAA;IAChC,UAAU,CAAkB;IAC5B,MAAM,CAAS;IACf,QAAQ,CAAS;IACjB,QAAQ,CAAS;IACjB,KAAK,GAAG,KAAK,CAAA;IACb,UAAU,CAAS;IACnB,OAAO,CAAe;IACtB,MAAM,CAAc;IAE9B,aAAa;IACH,OAAO,CAAe;IACtB,YAAY,CAAqB;IAE3C,qEAAqE;IACrE,+DAA+D;IAC/D,8DAA8D;IACpD,UAAU,CAAiC;IAErD,kEAAkE;IAClE,gEAAgE;IAChE,kDAAkD;IACxC,YAAY,GAAiB,EAAE,CAAA;IAEzC,kEAAkE;IAClE,wEAAwE;IAC9D,mBAAmB,GAAG,KAAK,CAAA;IAC3B,SAAS,GAAG,KAAK,CAAA;IACjB,YAAY,CAAS;IAC/B,wEAAwE;IACxE,8EAA8E;IACpE,SAAS,CAAqB;IAC9B,SAAS,GAA6B,IAAI,CAAA;IAEpD,qEAAqE;IACrE,oEAAoE;IACpE,sEAAsE;IAC5D,WAAW,GAAmC,KAAK,CAAA;IAE7D,8DAA8D;IAC9D,mEAAmE;IACnE,iEAAiE;IACjE,iDAAiD;IACvC,SAAS,GAAG,KAAK,CAAA;IACjB,WAAW,GAAgB,EAAE,CAAA;IAC7B,QAAQ,CAAS;IACjB,eAAe,GAAG,KAAK,CAAA;IACvB,WAAW,CAAmB;IAC9B,mBAAmB,CAAgB;IACnC,kBAAkB,CAAiB;IAE7C,YAAsB,IAAY;QAChC,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,IAAY;QACtB,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,yDAAyD;IAEzD,KAAK,CAAC,CAAS,IAAU,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IACvD,QAAQ,CAAC,CAAC,GAAG,IAAI,IAAU,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAC5D,UAAU,CAAC,CAAC,GAAG,IAAI,IAAU,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAEhE;;;;;;;;;;;;;;;;;OAiBG;IACH,UAAU,CAAC,OAAyC,IAAI;QACtD,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACnB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;QAC1B,CAAC;aAAM,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAA;QACvB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,WAAW,GAAG,EAAE,GAAG,IAAI,EAAE,CAAA;QAChC,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,YAAY,KAAc,OAAO,IAAI,CAAC,WAAW,KAAK,KAAK,CAAA,CAAC,CAAC;IAC7D,mBAAmB;QACjB,OAAO,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAA;IAClE,CAAC;IAED,yDAAyD;IAEzD,SAAS,CAAC,CAAkB,IAAU,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IACxE,KAAK,CAAC,CAAS,IAAU,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAEvD,uEAAuE;IACvE,OAAO,CAAC,CAAS,IAAU,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAC3D,4DAA4D;IAC5D,WAAW,CAAC,CAAS,IAAU,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA,CAAC,CAAC;IAEvD,OAAO,CAAC,CAAS,IAAU,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAE3D;sDACkD;IAClD,IAAI,CAAC,CAAC,GAAG,IAAI,IAAU,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAEpD,kEAAkE;IAClE,SAAS,CAAC,CAAS,IAAU,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAE/D,MAAM,CAAC,CAAe,IAAU,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAC/D,KAAK,CAAC,CAAc,IAAU,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAE5D,yDAAyD;IAEzD;uEACmE;IACnE,QAAQ,CAAC,OAAgB;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAA;QAC7E,OAAO,IAAI,CAAA;IACb,CAAC;IAED,2DAA2D;IAC3D,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;QAChC,OAAO,IAAI,CAAA;IACb,CAAC;IAED;8BAC0B;IAC1B,KAAK,CAAC,QAAgB,EAAE,MAAe;QACrC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAA;QACzF,OAAO,IAAI,CAAA;IACb,CAAC;IAED,4CAA4C;IAC5C,OAAO,CAAC,OAA+C,EAAE;QACvD,IAAI,CAAC,OAAO,GAAG;YACb,IAAI,EAAE,SAAS;YACf,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,IAAI,CAAC,MAAM,KAAO,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAI,IAAI,CAAC,MAAM,EAAI,CAAC,CAAC,CAAC,EAAE,CAAC;SACpE,CAAA;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,gEAAgE;IAChE,KAAK,CAAC,KAAa;QACjB,IAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;QACvC,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,CAAS;QACb,IAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;QAC1C,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACH,UAAU,CAAC,CAAS,IAAU,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA,CAAC,CAAC;IAEpD;;;;;OAKG;IACH,kBAAkB,CAAC,CAAC,GAAG,IAAI,IAAU,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAEhF;;;;OAIG;IACH,QAAQ,CAAC,CAAC,GAAG,IAAI,IAAU,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAE5D;;;;;;;OAOG;IACH,WAAW,CAAC,OAAgB;QAC1B,IAAI,CAAC,YAAY,GAAG,OAAO,IAAI,SAAS,CAAA;QACxC,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,CAAC,GAAG,IAAI;QACf,IAAI,CAAC;YAAE,IAAI,CAAC,SAAS,GAAG,UAAU,CAAA;;YAC7B,OAAO,IAAI,CAAC,SAAS,CAAA;QAC1B,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,CAAC,GAAG,IAAI;QACX,IAAI,CAAC;YAAE,IAAI,CAAC,SAAS,GAAG,MAAM,CAAA;;YACzB,OAAO,IAAI,CAAC,SAAS,CAAA;QAC1B,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAA8B,IAAI;QACzC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAA;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,uDAAuD;IACvD,QAAQ,KAAW,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAExD;;4DAEwD;IACxD,gBAAgB,CAAC,EAAsB;QACrC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAA;QACtB,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;;;;OASG;IACH,SAAS,CAAC,MAAsC;QAC9C,IAAI,CAAC,UAAU,GAAG,MAAM,CAAA;QACxB,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,WAAyB;QACjC,IAAI,CAAC,YAAY,GAAG,WAAW,CAAA;QAC/B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,yDAAyD;IACzD,qEAAqE;IACrE,mEAAmE;IACnE,qEAAqE;IACrE,oDAAoD;IAEpD;;8EAE0E;IAC1E,QAAQ,CAAC,CAAC,GAAG,IAAI,IAAU,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAE5D;;;;;;OAMG;IACH,QAAQ,CAAC,CAA0B;QACjC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;;YAC5C,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC7B,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,OAAe,IAAU,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAEvE;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAiB,IAAU,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAE1F;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAiB,IAAU,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAExF,qBAAqB,KAAgC,OAAO,IAAI,CAAC,mBAAmB,CAAA,CAAC,CAAC;IACtF,oBAAoB,KAAiC,OAAO,IAAI,CAAC,kBAAkB,CAAA,CAAC,CAAC;IAErF;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAoC,IAAI;QAC/C,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;YAChC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;YACxB,IAAI,CAAC,eAAe,GAAG,KAAK,CAAA;QAC9B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,eAAe,GAAG,KAAK,CAAA;YAC5B,OAAO,IAAI,CAAC,WAAW,CAAA;QACzB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,yDAAyD;IAE/C,aAAa,CAAC,CAAa;QACnC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAA;QACpB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,yDAAyD;IAEzD,QAAQ;QACN,OAAO,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC9E,CAAC;IACD,UAAU,KAAc,OAAO,IAAI,CAAC,SAAS,CAAA,CAAC,CAAC;IAC/C,YAAY,KAAc,OAAO,IAAI,CAAC,WAAW,CAAA,CAAC,CAAC;IACnD,aAAa,KAAiB,OAAO,IAAI,CAAC,WAAW,CAAA,CAAC,CAAC;IACvD,qBAAqB,KAAqC,OAAO,IAAI,CAAC,YAAY,CAAA,CAAC,CAAC;IACpF,YAAY,KAAc,OAAO,IAAI,CAAC,YAAY,KAAK,SAAS,CAAA,CAAC,CAAC;IAClE;;8DAE0D;IAC1D,SAAS,KAAc,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,CAAA,CAAC,CAAC;IAC1D,mBAAmB;QACjB,OAAO,OAAO,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAA;IAC5E,CAAC;IACD,mBAAmB,KAAc,OAAO,OAAO,IAAI,CAAC,UAAU,KAAK,UAAU,CAAA,CAAC,CAAC;IAC/E,mBAAmB,KAAc,OAAO,IAAI,CAAC,UAAU,KAAK,KAAK,CAAA,CAAC,CAAC;IACnE,cAAc,KAAgC,OAAO,IAAI,CAAC,YAAY,CAAA,CAAC,CAAC;IACxE,cAAc,KAAc,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAA,CAAC,CAAC;IAEjE;6EACyE;IACzE,eAAe,KAAqC,OAAO,IAAI,CAAC,SAAS,CAAA,CAAC,CAAC;IAC3E,UAAU,KAAc,OAAO,IAAI,CAAC,SAAS,KAAK,SAAS,CAAA,CAAC,CAAC;IAC7D,WAAW,KAA+B,OAAO,IAAI,CAAC,SAAS,CAAA,CAAC,CAAC;IAEjE,yDAAyD;IAEzD;kEAC8D;IAC9D,UAAU;QACR,OAAO,IAAI,CAAC,WAAW,KAAK,WAAW;eAClC,IAAI,CAAC,WAAW,KAAK,QAAQ;eAC7B,IAAI,CAAC,WAAW,KAAK,QAAQ,CAAA;IACpC,CAAC;IAED;;;mDAG+C;IAC/C,aAAa,CAAC,MAA+B;QAC3C,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO,IAAI,CAAA;QACrC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC;gBAAC,OAAO,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;YAAC,CAAC;YAChD,MAAM,CAAC;gBAAC,OAAO,IAAI,CAAA;YAAC,CAAC;QACvB,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,UAAU,KAAc,OAAO,IAAI,CAAC,SAAS,CAAA,CAAC,CAAC;IAC/C,aAAa,KAA+B,OAAO,IAAI,CAAC,WAAW,CAAA,CAAC,CAAC;IAErE;;wEAEoE;IACpE,KAAK,CAAC,aAAa,CAAC,KAAc,EAAE,GAAsB;QACxD,MAAM,MAAM,GAAa,EAAE,CAAA;QAC3B,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YACnD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBAC1D,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAA;YACvC,CAAC;QACH,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YAClC,IAAI,MAAM;gBAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACjC,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAEO,oBAAoB;QAC1B,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,KAAK,UAAU,CAAC,CAAA;IACtE,CAAC;IAED,0DAA0D;IAChD,kBAAkB;QAC1B,MAAM,KAAK,GAAqB,EAAE,CAAA;QAClC,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YACnD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC,CAAA;QACrE,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACjC,IAAI,CAAC,CAAC,UAAU;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;QAC5C,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,yDAAyD;IAEhD,OAAO,KAAa,OAAO,QAAQ,CAAA,CAAC,CAAC;IAErC,MAAM;QACb,MAAM,IAAI,GAAe;YACvB,IAAI,EAAQ,QAAQ;YACpB,IAAI,EAAQ,IAAI,CAAC,IAAI;YACrB,KAAK,EAAO,IAAI,CAAC,QAAQ,EAAE;YAC3B,QAAQ,EAAI,IAAI,CAAC,SAAS;YAC1B,UAAU,EAAE,IAAI,CAAC,WAAW;SAC7B,CAAA;QACD,2DAA2D;QAC3D,IAAI,IAAI,CAAC,WAAW,KAAK,MAAM;YAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,WAAW,CAAA;QACnE,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;YAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAA;QACnE,IAAI,IAAI,CAAC,MAAM,KAAS,SAAS;YAAE,IAAI,CAAC,KAAK,GAAO,IAAI,CAAC,MAAM,CAAA;QAC/D,IAAI,IAAI,CAAC,QAAQ,KAAO,SAAS;YAAE,IAAI,CAAC,OAAO,GAAK,IAAI,CAAC,QAAQ,CAAA;QACjE,IAAI,IAAI,CAAC,QAAQ,KAAO,SAAS;YAAE,IAAI,CAAC,OAAO,GAAK,IAAI,CAAC,QAAQ,CAAA;QACjE,IAAI,IAAI,CAAC,KAAK;YAAqB,IAAI,CAAC,IAAI,GAAQ,IAAI,CAAA;QACxD,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;YAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAA;QACnE,IAAI,IAAI,CAAC,OAAO,KAAQ,SAAS;YAAE,IAAI,CAAC,MAAM,GAAM,IAAI,CAAC,OAAO,CAAA;QAChE,IAAI,IAAI,CAAC,MAAM,KAAS,SAAS;YAAE,IAAI,CAAC,KAAK,GAAO,IAAI,CAAC,MAAM,CAAA;QAC/D,IAAI,IAAI,CAAC,OAAO,KAAQ,SAAS;YAAE,IAAI,CAAC,MAAM,GAAM,IAAI,CAAC,OAAO,CAAA;QAChE,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;YAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;QAC7D,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAA;QACzF,IAAI,IAAI,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;YAC/B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACrF,CAAC;QACD,IAAI,IAAI,CAAC,mBAAmB;YAAS,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAA;QACnE,IAAI,IAAI,CAAC,SAAS;YAAmB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;QACzD,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;YAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAA;QACzE,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;YAAK,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAA;QACnE,IAAI,IAAI,CAAC,UAAU,KAAK,KAAK;YAAS,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;aACvD,IAAI,OAAO,IAAI,CAAC,UAAU,KAAK,UAAU;YAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrE,kEAAkE;QAClE,qEAAqE;QACrE,mEAAmE;QACnE,iEAAiE;QACjE,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;gBAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAA;YAC7D,IAAI,IAAI,CAAC,eAAe;gBAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;YAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAA;YACvC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAC1C,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;QAC1B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,yEAAyE;IAC/D,eAAe,CAAC,KAAiB,IAAS,CAAC;CACtD"}
|
package/dist/Page.d.ts
CHANGED
|
@@ -6,9 +6,11 @@ import { type IconValue } from './icons/types.js';
|
|
|
6
6
|
/**
|
|
7
7
|
* Discriminator the framework uses for default rendering, route generation,
|
|
8
8
|
* and breadcrumbs. `'custom'` is for standalone Pages that don't belong to
|
|
9
|
-
* a Resource.
|
|
9
|
+
* a Resource. `'record'` is for record-scoped sub-pages declared under a
|
|
10
|
+
* Resource's `pages().record` map. The other four modes correspond to the
|
|
11
|
+
* standard resource page roles.
|
|
10
12
|
*/
|
|
11
|
-
export type PageMode = 'list' | 'create' | 'edit' | 'view' | 'custom';
|
|
13
|
+
export type PageMode = 'list' | 'create' | 'edit' | 'view' | 'record' | 'custom';
|
|
12
14
|
export interface PageMeta {
|
|
13
15
|
slug: string;
|
|
14
16
|
label: string;
|
|
@@ -71,8 +73,15 @@ export declare class Page {
|
|
|
71
73
|
/** Plan #10: authorization. Custom pages get a single `canAccess` gate
|
|
72
74
|
* (no per-record predicates — pages are too freeform to assume a
|
|
73
75
|
* record concept). Resource-bound default page subclasses can still
|
|
74
|
-
* read their owning resource's predicates via `getResource()`.
|
|
75
|
-
|
|
76
|
+
* read their owning resource's predicates via `getResource()`.
|
|
77
|
+
*
|
|
78
|
+
* Record sub-pages (declared under `ResourcePages.record`) receive
|
|
79
|
+
* the loaded parent record as the second argument so subclasses can
|
|
80
|
+
* gate on record state in addition to user. The parameter is
|
|
81
|
+
* optional so existing custom-page subclasses with `canAccess(user)`
|
|
82
|
+
* keep type-checking. Record-aware sub-pages typically override as
|
|
83
|
+
* `canAccess(user, record)`. */
|
|
84
|
+
static canAccess(_user: unknown, _record?: unknown): Promise<boolean>;
|
|
76
85
|
/**
|
|
77
86
|
* Optional back-reference to the owning Resource. Auto-generated default
|
|
78
87
|
* pages set this; user subclasses may override for breadcrumb / title
|
package/dist/Page.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Page.d.ts","sourceRoot":"","sources":["../src/Page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAChG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,kBAAkB,CAAA;AAEhE
|
|
1
|
+
{"version":3,"file":"Page.d.ts","sourceRoot":"","sources":["../src/Page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAChG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,kBAAkB,CAAA;AAEhE;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAEhF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAG,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,qFAAqF;IACrF,IAAI,EAAG,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;IAC7C,IAAI,EAAG,QAAQ,CAAA;CAChB;AAED,qBAAa,IAAI;IACf,uEAAuE;IACvE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IAEpB,4EAA4E;IAC5E,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IAErB;;;;sDAIkD;IAClD,MAAM,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;IAIvB,MAAM,CAAC,eAAe,EAAQ,MAAM,GAAG,SAAS,CAAY;IAC5D,MAAM,CAAC,cAAc,EAAS,MAAM,GAAG,SAAS,CAAY;IAC5D,MAAM,CAAC,eAAe,EAAQ,MAAM,GAAG,SAAS,CAAY;IAC5D,MAAM,CAAC,cAAc,EAAS,SAAS,CAAqB;IAC5D,MAAM,CAAC,eAAe,EAAQ,sBAAsB,GAAG,SAAS,CAAY;IAC5E,MAAM,CAAC,oBAAoB,EAAG,oBAAoB,CAAY;IAC9D,MAAM,CAAC,oBAAoB,EAAG,MAAM,GAAG,SAAS,CAAY;IAE5D;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,YAAY,CAAA;IAE7B,gCAAgC;IAChC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IAE9C;;;;;;;;;OASG;IACH,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,IAAI;IAKjD;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAOnE,MAAM,CAAC,OAAO,IAAI,MAAM;IAKxB,MAAM,CAAC,QAAQ,IAAI,MAAM;IAMzB,+EAA+E;IAC/E,MAAM,CAAC,kBAAkB,IAAI,MAAM;IAInC,uEAAuE;IACvE,MAAM,CAAC,iBAAiB,IAAI,SAAS;IAIrC,MAAM,CAAC,SAAS,IAAI,OAAO;IAI3B;;;;;;;;;;oCAUgC;WACnB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAE3E;;;;OAIG;IACH,MAAM,CAAC,WAAW,IAAI,aAAa,GAAG,SAAS;IAE/C;;;OAGG;IACH,MAAM,CAAC,OAAO,IAAI,QAAQ;IAE1B,gBAAgB;IAChB,MAAM,CAAC,MAAM,IAAI,QAAQ;CAW1B"}
|
package/dist/Page.js
CHANGED
|
@@ -78,8 +78,15 @@ export class Page {
|
|
|
78
78
|
/** Plan #10: authorization. Custom pages get a single `canAccess` gate
|
|
79
79
|
* (no per-record predicates — pages are too freeform to assume a
|
|
80
80
|
* record concept). Resource-bound default page subclasses can still
|
|
81
|
-
* read their owning resource's predicates via `getResource()`.
|
|
82
|
-
|
|
81
|
+
* read their owning resource's predicates via `getResource()`.
|
|
82
|
+
*
|
|
83
|
+
* Record sub-pages (declared under `ResourcePages.record`) receive
|
|
84
|
+
* the loaded parent record as the second argument so subclasses can
|
|
85
|
+
* gate on record state in addition to user. The parameter is
|
|
86
|
+
* optional so existing custom-page subclasses with `canAccess(user)`
|
|
87
|
+
* keep type-checking. Record-aware sub-pages typically override as
|
|
88
|
+
* `canAccess(user, record)`. */
|
|
89
|
+
static async canAccess(_user, _record) { return true; }
|
|
83
90
|
/**
|
|
84
91
|
* Optional back-reference to the owning Resource. Auto-generated default
|
|
85
92
|
* pages set this; user subclasses may override for breadcrumb / title
|
package/dist/Page.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Page.js","sourceRoot":"","sources":["../src/Page.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkB,aAAa,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"Page.js","sourceRoot":"","sources":["../src/Page.ts"],"names":[],"mappings":"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"}
|