@pilotiq/pilotiq 0.11.0 → 0.13.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 +2 -2
- package/CHANGELOG.md +21 -0
- package/dist/react/AppShell.d.ts +1 -1
- package/dist/react/AppShell.d.ts.map +1 -1
- package/dist/react/AppShell.js +7 -1
- package/dist/react/AppShell.js.map +1 -1
- package/dist/react/CollabTextRendererRegistry.d.ts +75 -0
- package/dist/react/CollabTextRendererRegistry.d.ts.map +1 -0
- package/dist/react/CollabTextRendererRegistry.js +18 -0
- package/dist/react/CollabTextRendererRegistry.js.map +1 -0
- package/dist/react/CurrentUserContext.d.ts +39 -0
- package/dist/react/CurrentUserContext.d.ts.map +1 -0
- package/dist/react/CurrentUserContext.js +27 -0
- package/dist/react/CurrentUserContext.js.map +1 -0
- package/dist/react/FormCollabBindingRegistry.d.ts +17 -84
- package/dist/react/FormCollabBindingRegistry.d.ts.map +1 -1
- package/dist/react/FormCollabBindingRegistry.js.map +1 -1
- package/dist/react/FormStateContext.d.ts +1 -35
- package/dist/react/FormStateContext.d.ts.map +1 -1
- package/dist/react/FormStateContext.js +7 -91
- package/dist/react/FormStateContext.js.map +1 -1
- package/dist/react/RowCoordsContext.d.ts +19 -0
- package/dist/react/RowCoordsContext.d.ts.map +1 -0
- package/dist/react/RowCoordsContext.js +6 -0
- package/dist/react/RowCoordsContext.js.map +1 -0
- package/dist/react/fields/BuilderInput.d.ts.map +1 -1
- package/dist/react/fields/BuilderInput.js +14 -9
- package/dist/react/fields/BuilderInput.js.map +1 -1
- package/dist/react/fields/MarkdownInput.d.ts.map +1 -1
- package/dist/react/fields/MarkdownInput.js +70 -101
- package/dist/react/fields/MarkdownInput.js.map +1 -1
- package/dist/react/fields/RepeaterInput.d.ts.map +1 -1
- package/dist/react/fields/RepeaterInput.js +26 -17
- package/dist/react/fields/RepeaterInput.js.map +1 -1
- package/dist/react/fields/TextLikeInput.d.ts +11 -9
- package/dist/react/fields/TextLikeInput.d.ts.map +1 -1
- package/dist/react/fields/TextLikeInput.js +111 -164
- package/dist/react/fields/TextLikeInput.js.map +1 -1
- package/dist/react/formStateHelpers.d.ts +0 -15
- package/dist/react/formStateHelpers.d.ts.map +1 -1
- package/dist/react/formStateHelpers.js +0 -91
- package/dist/react/formStateHelpers.js.map +1 -1
- package/dist/react/index.d.ts +3 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -1
- package/package.json +5 -5
- package/src/react/AppShell.tsx +11 -1
- package/src/react/CollabTextRendererRegistry.ts +84 -0
- package/src/react/CurrentUserContext.tsx +50 -0
- package/src/react/FormCollabBindingRegistry.ts +17 -77
- package/src/react/FormStateContext.tsx +6 -125
- package/src/react/RowCoordsContext.tsx +23 -0
- package/src/react/fields/BuilderInput.tsx +22 -10
- package/src/react/fields/MarkdownInput.tsx +125 -95
- package/src/react/fields/RepeaterInput.tsx +41 -16
- package/src/react/fields/TextLikeInput.tsx +147 -181
- package/src/react/formStateHelpers.test.ts +0 -99
- package/src/react/formStateHelpers.ts +0 -83
- package/src/react/index.ts +12 -2
- package/dist/react/fields/textDelta.d.ts +0 -44
- package/dist/react/fields/textDelta.d.ts.map +0 -1
- package/dist/react/fields/textDelta.js +0 -80
- package/dist/react/fields/textDelta.js.map +0 -1
- package/src/react/fields/textDelta.test.ts +0 -141
- package/src/react/fields/textDelta.ts +0 -86
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
> @pilotiq/pilotiq@0.
|
|
2
|
+
> @pilotiq/pilotiq@0.13.0 build /home/runner/work/pilotiq/pilotiq/packages/pilotiq
|
|
3
3
|
> tsc -p tsconfig.build.json && pnpm run copy-assets
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @pilotiq/pilotiq@0.
|
|
6
|
+
> @pilotiq/pilotiq@0.13.0 copy-assets /home/runner/work/pilotiq/pilotiq/packages/pilotiq
|
|
7
7
|
> mkdir -p dist/styles && cp -R src/styles/*.css dist/styles/
|
|
8
8
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @pilotiq/pilotiq
|
|
2
2
|
|
|
3
|
+
## 0.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Row-text Tiptap-backed collab — extends Phase D's Y.XmlFragment text-CRDT path to Repeater / Builder row leaves.
|
|
8
|
+
|
|
9
|
+
- **New:** `RowCoordsContext` + `useRowCoords()` (`@pilotiq/pilotiq/react`). `RepeaterInput` and `BuilderInput` wrap each row in the provider so dotted-path text leaves can compose a stable fragment key `${arrayName}.${rowId}.${fieldName}` that survives reorders. `TextLikeInput` + `MarkdownInput` collab branches both consume the coords.
|
|
10
|
+
- **Breaking — `FormCollabBinding` contract:** removed `getTextBinding?(name)` and `getRowTextBinding?(arrayName, rowId, fieldName)`. Text CRDT (top-level and row leaves) now lives exclusively in `@pilotiq/tiptap`'s `CollabTextRenderer` (`Y.XmlFragment`-backed via y-prosemirror). Bindings that implemented these methods can simply drop them; the renderer no longer asks.
|
|
11
|
+
- **Breaking — public exports:** removed `TextBinding` and `TextDelta` from `@pilotiq/pilotiq/react`. Internal-only types `BoundTextInput`, `textDelta.ts` deleted alongside.
|
|
12
|
+
- **Breaking — `FormStateApi`:** removed `textBindings`, `rowTextLeaves`, `getRowTextBinding`. `useFieldState(...).textBinding` is gone too; row-text consumers don't need to branch on it anymore (the Tiptap path is the only path).
|
|
13
|
+
|
|
14
|
+
Migration: pair this release with `@pilotiq-pro/collab` ≥ the matching cut. Pre-fix installs of `@pilotiq-pro/collab` will hit a TS error against the new contract; the matching collab release removes the dead methods.
|
|
15
|
+
|
|
16
|
+
## 0.12.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- Add `CurrentUserContext` exported from `@pilotiq/pilotiq/react` so plugins can read the active user (driven by `Pilotiq.user(req => …)`) without prop-drilling through `panel`. `AppShell` mounts the provider around the layout-provider chain seeded from `panel.userMenu?.user`; plugins call `useCurrentUser()` from inside any layout provider or descendant component.
|
|
21
|
+
|
|
22
|
+
Also fixes collab text field chrome: the single-line `TextLikeInput.tsx` chrome now uses `overflow-x-clip` instead of `overflow-x-auto` so `CollaborationCaret` user-name labels can escape the input upward (CSS spec: `auto` on either axis forces the other axis to non-visible too; `clip` is the one non-visible value that allows the orthogonal axis to remain `visible`). Trade-off: long text gets clipped on the right rather than horizontally scrollable inside a collab field — acceptable for plain-text fields where the presence label is the higher-value affordance.
|
|
23
|
+
|
|
3
24
|
## 0.11.0
|
|
4
25
|
|
|
5
26
|
### Minor Changes
|
package/dist/react/AppShell.d.ts
CHANGED
|
@@ -83,5 +83,5 @@ export interface AppShellProps {
|
|
|
83
83
|
componentSlotRegistry?: ComponentSlotRegistry;
|
|
84
84
|
children: React.ReactNode;
|
|
85
85
|
}
|
|
86
|
-
export declare function AppShell({ layout, notifications, componentRegistry, rightPanelRegistry, layoutProviderRegistry, ...props }: AppShellProps):
|
|
86
|
+
export declare function AppShell({ layout, notifications, componentRegistry, rightPanelRegistry, layoutProviderRegistry, ...props }: AppShellProps): import("react/jsx-runtime").JSX.Element;
|
|
87
87
|
//# sourceMappingURL=AppShell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../src/react/AppShell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAKlD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAInE,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAEhF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACxG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAErD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../src/react/AppShell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAKlD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAInE,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAEhF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACxG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAErD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAGjE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;QAC3C,oEAAoE;QACpE,UAAU,CAAC,EAAE,OAAO,EAAE,CAAA;QACtB;sEAC8D;QAC9D,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;QAC9B;;qEAE6D;QAC7D,qBAAqB,CAAC,EAAE,yBAAyB,CAAA;QACjD;;yEAEiE;QACjE,YAAY,CAAC,EAAE,gBAAgB,CAAA;QAC/B;;wEAEgE;QAChE,YAAY,CAAC,EAAE,eAAe,CAAA;QAC9B;;;yCAGiC;QACjC,WAAW,CAAC,EAAE,aAAa,CAAA;QAC3B,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB;;;iEAGyD;QACzD,iBAAiB,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;KACtC,CAAA;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IAC7B;8CAC0C;IAC1C,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAClC;;;;wCAIoC;IACpC,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;IACvC;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC;QAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;IAC7G;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,QAAQ,CAAC,EAAE,MAAkB,EAAE,aAAa,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,2CAqGrJ"}
|
package/dist/react/AppShell.js
CHANGED
|
@@ -11,6 +11,7 @@ import { RightSidebar } from './RightSidebar.js';
|
|
|
11
11
|
import { RecordWrapperGate } from './RecordWrapperGate.js';
|
|
12
12
|
import { useIsMobile } from './hooks/use-mobile.js';
|
|
13
13
|
import { RenderHookSlot } from './RenderHookSlot.js';
|
|
14
|
+
import { CurrentUserProvider } from './CurrentUserContext.js';
|
|
14
15
|
export function AppShell({ layout = 'sidebar', notifications, componentRegistry, rightPanelRegistry, layoutProviderRegistry, ...props }) {
|
|
15
16
|
const Layout = layout === 'topbar' ? TopbarLayout : SidebarLayout;
|
|
16
17
|
// exactOptionalPropertyTypes: only spread `initialNotifications` when set.
|
|
@@ -53,7 +54,12 @@ export function AppShell({ layout = 'sidebar', notifications, componentRegistry,
|
|
|
53
54
|
// provider sits OUTERMOST (closest to the layout root); LAST sits
|
|
54
55
|
// INNERMOST (closest to the page tree). Empty / unset → no wrap.
|
|
55
56
|
const wrapped = wrapInLayoutProviders(_jsx(ComponentRegistryProvider, { value: componentRegistry, children: _jsx(RightPanelRegistryProvider, { value: rightPanelRegistry, children: rightSidebarMeta ? (_jsx(RightSidebarProvider, { meta: rightSidebarMeta, basePath: props.basePath, children: inner })) : (inner) }) }), layoutProviderRegistry, props.basePath);
|
|
56
|
-
|
|
57
|
+
// `CurrentUserProvider` sits OUTSIDE the layout-provider chain so
|
|
58
|
+
// plugin-registered providers (e.g. `@pilotiq-pro/collab`'s
|
|
59
|
+
// CollabProvider, which threads the user into CollaborationCaret
|
|
60
|
+
// presence labels) can read the active user via `useCurrentUser()`.
|
|
61
|
+
// Value source mirrors what the top-right user dropdown renders.
|
|
62
|
+
return (_jsx(CurrentUserProvider, { value: props.panel.userMenu?.user ?? null, children: wrapped }));
|
|
57
63
|
}
|
|
58
64
|
/**
|
|
59
65
|
* Fold registered layout providers around `tree` from last to first so
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppShell.js","sourceRoot":"","sources":["../../src/react/AppShell.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAG5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAA;AAE7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAA;AACtE,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAwB,MAAM,wBAAwB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAGnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"AppShell.js","sourceRoot":"","sources":["../../src/react/AppShell.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAG5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAA;AAE7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAA;AACtE,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAwB,MAAM,wBAAwB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAGnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AA0E7D,MAAM,UAAU,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,GAAG,KAAK,EAAiB;IACpJ,MAAM,MAAM,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAA;IACjE,2EAA2E;IAC3E,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IAEjF,oEAAoE;IACpE,kEAAkE;IAClE,oEAAoE;IACpE,qEAAqE;IACrE,MAAM,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,IAAI,MAAM,CAAA;IACjE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAClC;QAAC,MAAwE,CAAC,0BAA0B,GAAG,iBAAiB,CAAA;IAC3H,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAEvB,sEAAsE;IACtE,oEAAoE;IACpE,qCAAqC;IACrC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACrD,MAAM,YAAY,GAKd;QACF,QAAQ,EAAM,KAAK,CAAC,QAAQ;QAC5B,IAAI,EAAU,WAAW;QACzB,YAAY,EAAE,cAAc;KAC7B,CAAA;IACD,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU;QAAE,YAAY,CAAC,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAA;IAE5E,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAA;IACrC,MAAM,gBAAgB,GAAG,KAAK,CAAC,KAAK,CAAC,YAAY,CAAA;IAEjD,qEAAqE;IACrE,8DAA8D;IAC9D,sEAAsE;IACtE,oEAAoE;IACpE,mCAAmC;IACnC,MAAM,WAAW,GAAG;QAClB,GAAG,KAAK;QACR,QAAQ,EAAE,CACR,KAAC,iBAAiB,IAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ,KACpB,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC3E,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,YAE7F,KAAK,CAAC,QAAQ,GACG,CACrB;KACF,CAAA;IAED,MAAM,KAAK,GAAG,CACZ,KAAC,eAAe,OAAK,YAAY,YAC/B,MAAC,sBAAsB,IAAC,OAAO,EAAE,cAAc,aAC7C,KAAC,cAAc,IAAC,IAAI,EAAC,oBAAoB,EAAC,KAAK,EAAE,KAAK,GAAI,EAC1D,KAAC,uBAAuB,cACtB,KAAC,MAAM,OAAK,WAAW,GAAI,GACH,EAC1B,KAAC,cAAc,IAAC,IAAI,EAAC,kBAAkB,EAAC,KAAK,EAAE,KAAK,GAAI,EACxD,KAAC,cAAc,OAAK,YAAY,GAAI,EACnC,gBAAgB,IAAI,CACnB,KAAC,YAAY,IACX,QAAQ,EAAE,KAAK,CAAC,QAAQ,KACpB,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAC/E,CACH,IACsB,GACT,CACnB,CAAA;IAED,iEAAiE;IACjE,qEAAqE;IACrE,kEAAkE;IAClE,iEAAiE;IACjE,MAAM,OAAO,GAAG,qBAAqB,CACnC,KAAC,yBAAyB,IAAC,KAAK,EAAE,iBAAiB,YACjD,KAAC,0BAA0B,IAAC,KAAK,EAAE,kBAAkB,YAClD,gBAAgB,CAAC,CAAC,CAAC,CAClB,KAAC,oBAAoB,IAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,YACnE,KAAK,GACe,CACxB,CAAC,CAAC,CAAC,CACF,KAAK,CACN,GAC0B,GACH,EAC5B,sBAAsB,EACtB,KAAK,CAAC,QAAQ,CACf,CAAA;IAED,kEAAkE;IAClE,4DAA4D;IAC5D,iEAAiE;IACjE,oEAAoE;IACpE,iEAAiE;IACjE,OAAO,CACL,KAAC,mBAAmB,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,IAAI,IAAI,YAC3D,OAAO,GACY,CACvB,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,qBAAqB,CAC5B,IAA4B,EAC5B,QAA0G,EAC1G,QAAgB;IAEhB,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACnD,IAAI,GAAG,GAAuB,IAAI,CAAA;IAClC,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAA;QAC7B,GAAG,GAAG,KAAC,QAAQ,IAAC,QAAQ,EAAE,QAAQ,YAAG,GAAG,GAAY,CAAA;IACtD,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,uBAAuB,CAAC,EAAE,QAAQ,EAAiC;IAC1E,MAAM,OAAO,GAAG,uBAAuB,EAAE,CAAA;IACzC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,KAAK,GAAG,OAAO,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAA;IAClD,iEAAiE;IACjE,kEAAkE;IAClE,qEAAqE;IACrE,eAAe;IACf,MAAM,KAAK,GAAoC,KAAK;QAClD,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,mCAAmC,EAAE;QACvF,CAAC,CAAC,EAAE,UAAU,EAAE,mCAAmC,EAAE,CAAA;IACvD,OAAO,cAAK,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAO,CAAA;AAC5C,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Module-level registry slot for the collab-aware plain-text editor renderer.
|
|
4
|
+
*
|
|
5
|
+
* Wiring posture (mirrors `CollabExtensionFactoryRegistry` /
|
|
6
|
+
* `FormCollabBindingRegistry`):
|
|
7
|
+
* - `@pilotiq/tiptap`'s `registerTiptap(...)` calls `registerCollabTextRenderer(...)`
|
|
8
|
+
* once at boot. The registered component closes over `@tiptap/*` imports so
|
|
9
|
+
* pilotiq core stays free of any tiptap peer dep — same posture as the
|
|
10
|
+
* existing rich-text renderer registry.
|
|
11
|
+
* - `TextLikeInput` checks for the registered component when a `<RecordCollabRoom>`
|
|
12
|
+
* is mounted up-tree AND the field hasn't opted out via `.collab(false)` AND
|
|
13
|
+
* the field has no `.mask()`. If present, the legacy `BoundTextInput`
|
|
14
|
+
* (Y.Text + `computeDelta` + heuristic `preserveCursor`) is bypassed in
|
|
15
|
+
* favour of a y-prosemirror-backed Tiptap editor that anchors selections to
|
|
16
|
+
* `Yjs.RelativePosition` — the architectural fix for the cursor-jump and
|
|
17
|
+
* two-peer concurrent-insert races documented in
|
|
18
|
+
* `docs/plans/text-fields-tiptap-backed-collab.md`.
|
|
19
|
+
*
|
|
20
|
+
* Wire props are deliberately framework-agnostic — the renderer doesn't take a
|
|
21
|
+
* `binding` since it consumes the room's `ydoc` directly via the existing
|
|
22
|
+
* `useCollabRoom()` + `getCollabExtensions()` plumbing on its own side. Core
|
|
23
|
+
* keeps the seam narrow: handler callbacks + DOM chrome only.
|
|
24
|
+
*/
|
|
25
|
+
export interface CollabTextRendererProps {
|
|
26
|
+
/** Field name — drives the `Y.XmlFragment` selector inside the collab adapter. */
|
|
27
|
+
name: string;
|
|
28
|
+
/** `true` for textarea-like (multiple paragraphs); `false` for input-like. */
|
|
29
|
+
multiline: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Server-rendered default value. The renderer is expected to seed the
|
|
32
|
+
* `Y.XmlFragment` from this on first connect when the room has no
|
|
33
|
+
* persisted state for this field (i.e. brand-new record).
|
|
34
|
+
*/
|
|
35
|
+
defaultValue: string;
|
|
36
|
+
/** Optional placeholder hint. */
|
|
37
|
+
placeholder?: string;
|
|
38
|
+
/** Disabled / read-only state. */
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
/** Fired on every editor `update` with the editor's current plain text. */
|
|
41
|
+
onChange: (text: string) => void;
|
|
42
|
+
/** Fired on editor blur — host wires this to live-onBlur trigger semantics. */
|
|
43
|
+
onBlur: () => void;
|
|
44
|
+
/**
|
|
45
|
+
* Single-line submit — fired when `multiline: false` AND the user presses
|
|
46
|
+
* Enter. The renderer is expected to blur the editor after invoking this.
|
|
47
|
+
* Multiline mode ignores it (Enter inserts a paragraph instead).
|
|
48
|
+
*/
|
|
49
|
+
onSubmit?: () => void;
|
|
50
|
+
/**
|
|
51
|
+
* Tailwind className applied to the editor's contenteditable wrapper so the
|
|
52
|
+
* rendered editor matches the native `<input>` / `<textarea>` chrome it
|
|
53
|
+
* replaces. The host owns the styling — the adapter just forwards.
|
|
54
|
+
*/
|
|
55
|
+
className?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Additional DOM attributes for the editor's contenteditable wrapper —
|
|
58
|
+
* typically `id`, `aria-*`, `autocomplete`, etc.
|
|
59
|
+
*/
|
|
60
|
+
editorAttributes?: Record<string, string>;
|
|
61
|
+
}
|
|
62
|
+
export type CollabTextRenderer = ComponentType<CollabTextRendererProps>;
|
|
63
|
+
/**
|
|
64
|
+
* Register the collab plain-text editor component. Called once at boot by
|
|
65
|
+
* `@pilotiq/tiptap`'s `registerTiptap()` (or directly by an app that imports
|
|
66
|
+
* the renderer). Calling with `null` clears the registry — useful for tests.
|
|
67
|
+
*
|
|
68
|
+
* No-op behaviour when no renderer is registered: `TextLikeInput` falls back
|
|
69
|
+
* to the legacy `BoundTextInput` path (or the plain controlled / uncontrolled
|
|
70
|
+
* input when no collab room is mounted).
|
|
71
|
+
*/
|
|
72
|
+
export declare function registerCollabTextRenderer(component: CollabTextRenderer | null): void;
|
|
73
|
+
/** Returns the registered component, or `null` when no adapter is installed. */
|
|
74
|
+
export declare function getCollabTextRenderer(): CollabTextRenderer | null;
|
|
75
|
+
//# sourceMappingURL=CollabTextRendererRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CollabTextRendererRegistry.d.ts","sourceRoot":"","sources":["../../src/react/CollabTextRendererRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAE1C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,uBAAuB;IACtC,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAA;IACZ,8EAA8E;IAC9E,SAAS,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAA;IACpB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2EAA2E;IAC3E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,+EAA+E;IAC/E,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC1C;AAED,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAAC,uBAAuB,CAAC,CAAA;AAIvE;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAErF;AAED,gFAAgF;AAChF,wBAAgB,qBAAqB,IAAI,kBAAkB,GAAG,IAAI,CAEjE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
let _renderer = null;
|
|
2
|
+
/**
|
|
3
|
+
* Register the collab plain-text editor component. Called once at boot by
|
|
4
|
+
* `@pilotiq/tiptap`'s `registerTiptap()` (or directly by an app that imports
|
|
5
|
+
* the renderer). Calling with `null` clears the registry — useful for tests.
|
|
6
|
+
*
|
|
7
|
+
* No-op behaviour when no renderer is registered: `TextLikeInput` falls back
|
|
8
|
+
* to the legacy `BoundTextInput` path (or the plain controlled / uncontrolled
|
|
9
|
+
* input when no collab room is mounted).
|
|
10
|
+
*/
|
|
11
|
+
export function registerCollabTextRenderer(component) {
|
|
12
|
+
_renderer = component;
|
|
13
|
+
}
|
|
14
|
+
/** Returns the registered component, or `null` when no adapter is installed. */
|
|
15
|
+
export function getCollabTextRenderer() {
|
|
16
|
+
return _renderer;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=CollabTextRendererRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CollabTextRendererRegistry.js","sourceRoot":"","sources":["../../src/react/CollabTextRendererRegistry.ts"],"names":[],"mappings":"AAiEA,IAAI,SAAS,GAA8B,IAAI,CAAA;AAE/C;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CAAC,SAAoC;IAC7E,SAAS,GAAG,SAAS,CAAA;AACvB,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,qBAAqB;IACnC,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Resolved identity of the user driving the current page. Mirrors the
|
|
4
|
+
* `UserMenuMeta.user` shape that `panelInfo()` ships to the renderer —
|
|
5
|
+
* whichever fields the `Pilotiq.user(req => …)` resolver populated.
|
|
6
|
+
*
|
|
7
|
+
* `null` is the no-user state: either the panel never wired a resolver,
|
|
8
|
+
* or the resolver returned `null` for this request. Consumers should
|
|
9
|
+
* gracefully fall back (no avatar, no presence label, etc.) rather than
|
|
10
|
+
* treating absence as an error.
|
|
11
|
+
*/
|
|
12
|
+
export interface CurrentUser {
|
|
13
|
+
name?: string;
|
|
14
|
+
email?: string;
|
|
15
|
+
avatar?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Mounted by `AppShell` around the layout-provider chain so plugins
|
|
19
|
+
* (collab user presence, audit-trail attribution, analytics
|
|
20
|
+
* client-side opt-outs, …) can read the active user via
|
|
21
|
+
* `useCurrentUser()` without prop-drilling through `panel`.
|
|
22
|
+
*
|
|
23
|
+
* Value source is `viewProps.panel.userMenu?.user` — the same shape the
|
|
24
|
+
* top-right dropdown renders. The provider sits OUTSIDE
|
|
25
|
+
* `layoutProviderRegistry` so plugin-registered layout providers can
|
|
26
|
+
* subscribe.
|
|
27
|
+
*/
|
|
28
|
+
export declare function CurrentUserProvider({ value, children, }: {
|
|
29
|
+
value: CurrentUser | null;
|
|
30
|
+
children: ReactNode;
|
|
31
|
+
}): ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* Read the active user inside any descendant of `<AppShell>`. Returns
|
|
34
|
+
* `null` outside an `AppShell` mount (defensive — keeps storybook /
|
|
35
|
+
* isolated-render tests from throwing) and when no user resolved for
|
|
36
|
+
* the request.
|
|
37
|
+
*/
|
|
38
|
+
export declare function useCurrentUser(): CurrentUser | null;
|
|
39
|
+
//# sourceMappingURL=CurrentUserContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CurrentUserContext.d.ts","sourceRoot":"","sources":["../../src/react/CurrentUserContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjE;;;;;;;;;GASG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAI,MAAM,CAAA;IACf,KAAK,CAAC,EAAG,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACzB,QAAQ,EAAE,SAAS,CAAA;CACpB,GAAG,SAAS,CAEZ;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAEnD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
const CurrentUserContext = createContext(null);
|
|
4
|
+
/**
|
|
5
|
+
* Mounted by `AppShell` around the layout-provider chain so plugins
|
|
6
|
+
* (collab user presence, audit-trail attribution, analytics
|
|
7
|
+
* client-side opt-outs, …) can read the active user via
|
|
8
|
+
* `useCurrentUser()` without prop-drilling through `panel`.
|
|
9
|
+
*
|
|
10
|
+
* Value source is `viewProps.panel.userMenu?.user` — the same shape the
|
|
11
|
+
* top-right dropdown renders. The provider sits OUTSIDE
|
|
12
|
+
* `layoutProviderRegistry` so plugin-registered layout providers can
|
|
13
|
+
* subscribe.
|
|
14
|
+
*/
|
|
15
|
+
export function CurrentUserProvider({ value, children, }) {
|
|
16
|
+
return _jsx(CurrentUserContext.Provider, { value: value, children: children });
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Read the active user inside any descendant of `<AppShell>`. Returns
|
|
20
|
+
* `null` outside an `AppShell` mount (defensive — keeps storybook /
|
|
21
|
+
* isolated-render tests from throwing) and when no user resolved for
|
|
22
|
+
* the request.
|
|
23
|
+
*/
|
|
24
|
+
export function useCurrentUser() {
|
|
25
|
+
return useContext(CurrentUserContext);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=CurrentUserContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CurrentUserContext.js","sourceRoot":"","sources":["../../src/react/CurrentUserContext.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAkB,MAAM,OAAO,CAAA;AAkBjE,MAAM,kBAAkB,GAAG,aAAa,CAAqB,IAAI,CAAC,CAAA;AAElE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,KAAK,EACL,QAAQ,GAIT;IACC,OAAO,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAA+B,CAAA;AAC5F,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,UAAU,CAAC,kBAAkB,CAAC,CAAA;AACvC,CAAC"}
|
|
@@ -1,51 +1,5 @@
|
|
|
1
1
|
import type { ElementMeta } from '../schema/Element.js';
|
|
2
2
|
import type { CollabRoom } from './CollabRoomContext.js';
|
|
3
|
-
/**
|
|
4
|
-
* Phase F.6 — character-level edit op emitted by `TextLikeInput` and
|
|
5
|
-
* applied through `TextBinding.applyDelta`. `replace` covers IME / paste
|
|
6
|
-
* / multi-char selections; `insert` and `delete` cover the single-key
|
|
7
|
-
* common path. Pilotiq core stays Yjs-free — the binding impl in
|
|
8
|
-
* `@pilotiq-pro/collab` translates these into `Y.Text.insert / delete`
|
|
9
|
-
* inside a transaction.
|
|
10
|
-
*/
|
|
11
|
-
export type TextDelta = {
|
|
12
|
-
kind: 'insert';
|
|
13
|
-
index: number;
|
|
14
|
-
text: string;
|
|
15
|
-
} | {
|
|
16
|
-
kind: 'delete';
|
|
17
|
-
index: number;
|
|
18
|
-
length: number;
|
|
19
|
-
} | {
|
|
20
|
-
kind: 'replace';
|
|
21
|
-
from: number;
|
|
22
|
-
to: number;
|
|
23
|
-
text: string;
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* Phase F.6 — per-field character-level CRDT handle. Issued by
|
|
27
|
-
* `FormCollabBinding.getTextBinding(name)` for text-shaped fields
|
|
28
|
-
* (`TextField / TextareaField / EmailField / SlugField / MarkdownField`);
|
|
29
|
-
* returns `null` for non-text fields or text fields opted out via
|
|
30
|
-
* `.collab(false)`. The surface stays intentionally narrow so pilotiq
|
|
31
|
-
* core never touches Yjs directly — same posture as `FormCollabBinding`.
|
|
32
|
-
*
|
|
33
|
-
* - `read()` returns the current full string. `TextLikeInput` calls
|
|
34
|
-
* this once on mount to seed its controlled value.
|
|
35
|
-
* - `applyDelta(delta)` is called from `onInput` events with a single
|
|
36
|
-
* `insert / delete / replace` op derived from the input's selection.
|
|
37
|
-
* - `observe(fn)` registers a remote-change listener; `fn(next)`
|
|
38
|
-
* receives the post-change string. Returns an unsubscribe function.
|
|
39
|
-
* - `destroy()` cleans up everything the handle holds. The owning
|
|
40
|
-
* `FormCollabBinding.destroy()` is expected to cascade — consumers
|
|
41
|
-
* don't need to call this directly.
|
|
42
|
-
*/
|
|
43
|
-
export interface TextBinding {
|
|
44
|
-
read(): string;
|
|
45
|
-
applyDelta(delta: TextDelta): void;
|
|
46
|
-
observe(fn: (next: string) => void): () => void;
|
|
47
|
-
destroy(): void;
|
|
48
|
-
}
|
|
49
3
|
/**
|
|
50
4
|
* Binding contract that a collab plugin returns from
|
|
51
5
|
* `registerFormCollabBinding` — wraps a single form's value map in a
|
|
@@ -62,14 +16,14 @@ export interface TextBinding {
|
|
|
62
16
|
* - `subscribe(fn)` registers a listener that fires when REMOTE
|
|
63
17
|
* changes land; `fn(snapshot)` receives the full updated map.
|
|
64
18
|
* The provider re-applies this snapshot onto its React state.
|
|
65
|
-
* - `getTextBinding(name)` (Phase F.6) returns a `Y.Text`-backed
|
|
66
|
-
* handle for text-shaped fields, or `null` for non-text fields and
|
|
67
|
-
* text fields opted out via `.collab(false)`. The text/non-text
|
|
68
|
-
* allowlist lives in the binding impl — `FormStateProvider` asks
|
|
69
|
-
* for every field and routes per-field on the answer.
|
|
70
19
|
* - `destroy()` is called on unmount — gives the plugin a chance to
|
|
71
|
-
* remove its CRDT observer.
|
|
72
|
-
*
|
|
20
|
+
* remove its CRDT observer.
|
|
21
|
+
*
|
|
22
|
+
* Text-field character-level CRDT lives in `@pilotiq/tiptap`'s
|
|
23
|
+
* `CollabTextRenderer` (`Y.XmlFragment` per field, keyed by bare name
|
|
24
|
+
* for top-level + `${arrayName}.${rowId}.${fieldName}` composite for
|
|
25
|
+
* row leaves) — pilotiq core no longer mediates per-field text CRDT,
|
|
26
|
+
* so this binding only handles non-text values + row lifecycle.
|
|
73
27
|
*
|
|
74
28
|
* `unknown` payloads keep pilotiq core Yjs-free; the binding owns its
|
|
75
29
|
* own type knowledge. Same posture as `CollabExtensionFactory`.
|
|
@@ -81,12 +35,6 @@ export interface FormCollabBinding {
|
|
|
81
35
|
set(name: string, value: unknown): void;
|
|
82
36
|
/** Subscribe to remote changes. Returns an unsubscribe function. */
|
|
83
37
|
subscribe(fn: (snapshot: Record<string, unknown>) => void): () => void;
|
|
84
|
-
/** Phase F.6 — per-field text-CRDT handle. Returns `null` for non-text
|
|
85
|
-
* fields or text fields opted out via `.collab(false)`. Optional so
|
|
86
|
-
* existing F1-era plugins keep type-checking without a no-op stub;
|
|
87
|
-
* when absent, every text field stays on today's whole-string LWW
|
|
88
|
-
* path (i.e. F.6 character-level CRDT is opt-in by impl). */
|
|
89
|
-
getTextBinding?(name: string): TextBinding | null;
|
|
90
38
|
/** Cleanup hook called when the form unmounts. */
|
|
91
39
|
destroy(): void;
|
|
92
40
|
/**
|
|
@@ -126,29 +74,16 @@ export interface FormCollabBinding {
|
|
|
126
74
|
/**
|
|
127
75
|
* Write a single field on a row. Replaces the dotted-path `set` for
|
|
128
76
|
* row leaves (`tags.0.label` → `setRow('tags', rowId, 'label', value)`).
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* scalar field-map under LWW.
|
|
77
|
+
* Non-text row fields land on the row's scalar field-map under LWW;
|
|
78
|
+
* text row fields don't flow through here — the Tiptap renderer
|
|
79
|
+
* writes them directly to a `Y.XmlFragment` at the doc root keyed by
|
|
80
|
+
* `${arrayName}.${rowId}.${fieldName}`.
|
|
134
81
|
*
|
|
135
82
|
* `FormStateProvider` calls this on every local edit when both a
|
|
136
83
|
* dotted-path name is being written AND `setRow` is implemented;
|
|
137
84
|
* otherwise the v1 skip-on-dot path runs.
|
|
138
85
|
*/
|
|
139
86
|
setRow?(arrayName: string, rowId: string, fieldName: string, value: unknown): void;
|
|
140
|
-
/**
|
|
141
|
-
* Per-row text-CRDT handle. Composes with F.6's `BoundTextInput`:
|
|
142
|
-
* the renderer asks for one of these when a row leaf is text-shaped
|
|
143
|
-
* AND not opted out via `.collab(false)`, then threads it through
|
|
144
|
-
* the existing `TextBinding` plumbing inside the row.
|
|
145
|
-
*
|
|
146
|
-
* Returns `null` for non-text fields, fields opted out via collab,
|
|
147
|
-
* rows not yet present in the binding's index (e.g. before
|
|
148
|
-
* `addRow` has propagated), or when the binding doesn't yet
|
|
149
|
-
* implement per-row text CRDT (deferred to F.5c).
|
|
150
|
-
*/
|
|
151
|
-
getRowTextBinding?(arrayName: string, rowId: string, fieldName: string): TextBinding | null;
|
|
152
87
|
/**
|
|
153
88
|
* Subscribe to row-lifecycle events for a Repeater/Builder array.
|
|
154
89
|
* Fires on remote add / remove / move; the renderer reconciles its
|
|
@@ -239,14 +174,12 @@ export interface FormCollabBindingFactoryArgs {
|
|
|
239
174
|
*/
|
|
240
175
|
initial: Record<string, unknown>;
|
|
241
176
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
* (
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
* structural changes from `live()` re-resolves aren't re-walked
|
|
249
|
-
* (rare in practice — dynamic field add/remove is an F-followup).
|
|
177
|
+
* Initial form meta from the server. The binding walks this once at
|
|
178
|
+
* construction to index Repeater / Builder array names for row-level
|
|
179
|
+
* CRDT. Text fields (top-level and row leaves alike) don't need to be
|
|
180
|
+
* partitioned here — the Tiptap renderer owns their `Y.XmlFragment`s
|
|
181
|
+
* at the doc root. The meta is captured at mount; later structural
|
|
182
|
+
* changes from `live()` re-resolves aren't re-walked.
|
|
250
183
|
*/
|
|
251
184
|
formMeta: ElementMeta;
|
|
252
185
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormCollabBindingRegistry.d.ts","sourceRoot":"","sources":["../../src/react/FormCollabBindingRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAExD
|
|
1
|
+
{"version":3,"file":"FormCollabBindingRegistry.d.ts","sourceRoot":"","sources":["../../src/react/FormCollabBindingRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormCollabBindingRegistry.js","sourceRoot":"","sources":["../../src/react/FormCollabBindingRegistry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FormCollabBindingRegistry.js","sourceRoot":"","sources":["../../src/react/FormCollabBindingRegistry.ts"],"names":[],"mappings":"AA4LA,IAAI,QAAQ,GAAoC,IAAI,CAAA;AAEpD;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAiC;IACzE,QAAQ,GAAG,OAAO,CAAA;AACpB,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,oBAAoB;IAClC,OAAO,QAAQ,CAAA;AACjB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ElementMeta } from '../schema/Element.js';
|
|
3
|
-
import { type RowBindingApi
|
|
3
|
+
import { type RowBindingApi } from './FormCollabBindingRegistry.js';
|
|
4
4
|
export type FieldStatus = 'idle' | 'pending';
|
|
5
5
|
export interface FormStateApi {
|
|
6
6
|
values: Record<string, unknown>;
|
|
@@ -20,36 +20,11 @@ export interface FormStateApi {
|
|
|
20
20
|
formMeta: ElementMeta;
|
|
21
21
|
inFlight: boolean;
|
|
22
22
|
fieldStatus: (name: string) => FieldStatus;
|
|
23
|
-
/** Phase F.6 — per-field text-CRDT handles stashed at collab-room mount.
|
|
24
|
-
* `null` outside a room or before the binding effect has populated the
|
|
25
|
-
* map. The text/non-text allowlist lives in the binding impl —
|
|
26
|
-
* `FormStateProvider` asks for every top-level field and only stashes
|
|
27
|
-
* non-null answers, so a `Map.get()` hit means the binding has opted
|
|
28
|
-
* this field into the character-level path. */
|
|
29
|
-
textBindings: ReadonlyMap<string, TextBinding> | null;
|
|
30
23
|
/** Phase F.5 — per-Repeater/Builder row-array bindings. `null` outside a
|
|
31
24
|
* collab room or when the binding doesn't implement F.5 row methods.
|
|
32
25
|
* Each entry's API methods are pre-bound to the array name so renderers
|
|
33
26
|
* call `.add(rowId, initial)` rather than `binding.addRow(name, …)`. */
|
|
34
27
|
rowBindings: ReadonlyMap<string, RowBindingApi> | null;
|
|
35
|
-
/**
|
|
36
|
-
* Phase F.5c — per-array set of inner-field names that should route
|
|
37
|
-
* through `Y.Text` (character-level CRDT) instead of row-level Y.Map
|
|
38
|
-
* LWW. Built from a single meta walk at binding mount. Read by
|
|
39
|
-
* `useFieldState(dottedName).textBinding` to decide whether to call
|
|
40
|
-
* `getRowTextBinding`. Sparse — only arrays with at least one
|
|
41
|
-
* text-shaped row leaf appear; absence on a key means "no text leaves
|
|
42
|
-
* in this Repeater/Builder".
|
|
43
|
-
*/
|
|
44
|
-
rowTextLeaves: ReadonlyMap<string, ReadonlySet<string>> | null;
|
|
45
|
-
/**
|
|
46
|
-
* Phase F.5c — resolve a per-row `TextBinding`. Pre-bound to the
|
|
47
|
-
* active F.5 binding so consumers don't reach for `bindingRef`
|
|
48
|
-
* directly. Returns `null` when no binding implements F.5c OR the
|
|
49
|
-
* row+field doesn't qualify (renderer caller should fall back to
|
|
50
|
-
* `defaultValue` like a non-collab form).
|
|
51
|
-
*/
|
|
52
|
-
getRowTextBinding: ((arrayName: string, rowId: string, fieldName: string) => TextBinding | null) | null;
|
|
53
28
|
}
|
|
54
29
|
/** Hook for direct access to the form context. Returns `null` outside a
|
|
55
30
|
* `FormStateProvider` (e.g. an action modal, or a form without any live
|
|
@@ -83,15 +58,6 @@ export interface UseFieldStateResult {
|
|
|
83
58
|
/** True while a live re-resolve POST is in flight for this field. */
|
|
84
59
|
pending: boolean;
|
|
85
60
|
errors: string[];
|
|
86
|
-
/** Phase F.6 — character-level CRDT handle for text-shaped fields when
|
|
87
|
-
* a collab room is mounted up-tree AND the binding strategy applies
|
|
88
|
-
* (allowlist + `.collab() !== false`). Null in every other case —
|
|
89
|
-
* outside a `FormStateProvider`, outside a `<RecordCollabRoom>`, on
|
|
90
|
-
* non-text fields, on dotted-path inner-Repeater rows (deferred to
|
|
91
|
-
* F.5), and on text fields opted out via `.collab(false)`. Text input
|
|
92
|
-
* renderers branch on this: non-null → character-level path with
|
|
93
|
-
* `applyDelta + observe`; null → today's whole-string LWW path. */
|
|
94
|
-
textBinding: TextBinding | null;
|
|
95
61
|
}
|
|
96
62
|
/**
|
|
97
63
|
* Phase F.5 — return the row-array CRDT API for a Repeater/Builder field.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormStateContext.d.ts","sourceRoot":"","sources":["../../src/react/FormStateContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"FormStateContext.d.ts","sourceRoot":"","sources":["../../src/react/FormStateContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAavD,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,gCAAgC,CAAA;AAEvC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAA;AAE5C,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtC,QAAQ,EAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IACrD;;;;;;qEAMiE;IACjE,WAAW,EAAI,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9D,MAAM,EAAS,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IACvC;8EAC0E;IAC1E,WAAW,EAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,IAAI,CAAA;IACzD,QAAQ,EAAO,WAAW,CAAA;IAC1B,QAAQ,EAAO,OAAO,CAAA;IACtB,WAAW,EAAI,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,CAAA;IAC5C;;;6EAGyE;IACzE,WAAW,EAAI,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,IAAI,CAAA;CACzD;AAID;;4DAE4D;AAC5D,wBAAgB,YAAY,IAAI,YAAY,GAAG,IAAI,CAElD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,uBAA4B,CAAA;AAEtD,MAAM,WAAW,mBAAmB;IAClC;;;;;;oDAMgD;IAChD,UAAU,EAAG,OAAO,CAAA;IACpB,KAAK,EAAQ,OAAO,CAAA;IACpB,QAAQ,EAAK,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACjC;;;;mBAIe;IACf,WAAW,EAAE,CAAC,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9C,qEAAqE;IACrE,OAAO,EAAM,OAAO,CAAA;IACpB,MAAM,EAAO,MAAM,EAAE,CAAA;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAIrE;AAED;;gEAEgE;AAChE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAuB/D;AAWD,MAAM,WAAW,sBAAsB;IACrC;oDACgD;IAChD,WAAW,EAAI,WAAW,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IACvC,QAAQ,EAAO,KAAK,CAAC,SAAS,CAAA;IAC9B,+EAA+E;IAC/E,SAAS,CAAC,EAAK,OAAO,KAAK,CAAA;IAC3B;gFAC4E;IAC5E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAA;IAC1C;;;;wDAIoD;IACpD,OAAO,CAAC,EAAO,KAAK,CAAC,SAAS,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;CACvD;AAED;;;uEAGuE;AACvE,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,aAAa,EACb,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,OAAO,GACR,EAAE,sBAAsB,GAAG,KAAK,CAAC,YAAY,CAiX7C"}
|