@pilotiq/pilotiq 0.8.2 → 0.9.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 +165 -0
- package/dist/Resource.d.ts +39 -0
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +30 -0
- package/dist/Resource.js.map +1 -1
- package/dist/pageData/navigation.d.ts +17 -1
- package/dist/pageData/navigation.d.ts.map +1 -1
- package/dist/pageData/navigation.js +14 -0
- package/dist/pageData/navigation.js.map +1 -1
- package/dist/react/AppShell.d.ts +5 -0
- package/dist/react/AppShell.d.ts.map +1 -1
- package/dist/react/AppShell.js +1 -1
- package/dist/react/AppShell.js.map +1 -1
- package/dist/react/FormCollabBindingRegistry.d.ts +71 -1
- package/dist/react/FormCollabBindingRegistry.d.ts.map +1 -1
- package/dist/react/FormCollabBindingRegistry.js.map +1 -1
- package/dist/react/FormStateContext.d.ts +17 -0
- package/dist/react/FormStateContext.d.ts.map +1 -1
- package/dist/react/FormStateContext.js +44 -3
- package/dist/react/FormStateContext.js.map +1 -1
- package/dist/react/RecordWrapperGate.d.ts +19 -6
- package/dist/react/RecordWrapperGate.d.ts.map +1 -1
- package/dist/react/RecordWrapperGate.js +18 -8
- package/dist/react/RecordWrapperGate.js.map +1 -1
- package/dist/react/fields/MarkdownInput.d.ts.map +1 -1
- package/dist/react/fields/MarkdownInput.js +105 -3
- package/dist/react/fields/MarkdownInput.js.map +1 -1
- package/dist/react/fields/TextLikeInput.d.ts +10 -0
- package/dist/react/fields/TextLikeInput.d.ts.map +1 -1
- package/dist/react/fields/TextLikeInput.js +179 -0
- package/dist/react/fields/TextLikeInput.js.map +1 -1
- package/dist/react/fields/textDelta.d.ts +44 -0
- package/dist/react/fields/textDelta.d.ts.map +1 -0
- package/dist/react/fields/textDelta.js +80 -0
- package/dist/react/fields/textDelta.js.map +1 -0
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/parseRecordEditUrl.d.ts +33 -9
- package/dist/react/parseRecordEditUrl.d.ts.map +1 -1
- package/dist/react/parseRecordEditUrl.js +40 -2
- package/dist/react/parseRecordEditUrl.js.map +1 -1
- package/package.json +1 -1
- package/src/Resource.test.ts +44 -0
- package/src/Resource.ts +58 -0
- package/src/pageData/navigation.ts +32 -1
- package/src/pageData.test.ts +36 -0
- package/src/react/AppShell.tsx +6 -1
- package/src/react/FormCollabBindingRegistry.ts +63 -1
- package/src/react/FormStateContext.tsx +62 -3
- package/src/react/RecordWrapperGate.tsx +26 -8
- package/src/react/fields/MarkdownInput.tsx +100 -3
- package/src/react/fields/TextLikeInput.tsx +203 -1
- package/src/react/fields/textDelta.test.ts +141 -0
- package/src/react/fields/textDelta.ts +86 -0
- package/src/react/index.ts +9 -1
- package/src/react/parseRecordEditUrl.test.ts +48 -1
- package/src/react/parseRecordEditUrl.ts +52 -13
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* URL → record-page identity parser. Used by `RecordWrapperGate` (and any
|
|
3
|
+
* plugin that wants to reason about record-bound URLs) to decide whether
|
|
4
|
+
* the current page is a record-edit or record-view route.
|
|
4
5
|
*
|
|
5
6
|
* A URL matches when:
|
|
6
7
|
* 1. it starts with the panel's `basePath`
|
|
7
|
-
* 2. after stripping the prefix it ends with `/edit`
|
|
8
|
+
* 2. after stripping the prefix it ends with `/edit` or `/view`
|
|
8
9
|
* 3. there are at least three remaining segments (resource slug,
|
|
9
|
-
* record id,
|
|
10
|
+
* record id, terminal token)
|
|
10
11
|
*
|
|
11
12
|
* The `resourceSlug` is the slash-joined chain of every segment up to
|
|
12
13
|
* the record id — this gives clustered resources (`${base}/blog/articles/123/edit`)
|
|
@@ -14,22 +15,40 @@
|
|
|
14
15
|
* distinct slugs so two URLs that target different records always
|
|
15
16
|
* produce different room names downstream.
|
|
16
17
|
*
|
|
17
|
-
* `/admin/articles/123/edit` → {
|
|
18
|
-
* `/admin/
|
|
19
|
-
* `/admin/articles/123/
|
|
20
|
-
* `/admin/articles/123/comments`
|
|
21
|
-
* `/admin/articles/123/comments
|
|
18
|
+
* `/admin/articles/123/edit` → { slug: 'articles', id: '123', role: 'edit' }
|
|
19
|
+
* `/admin/articles/123/view` → { slug: 'articles', id: '123', role: 'view' }
|
|
20
|
+
* `/admin/blog/articles/123/edit` → { slug: 'blog/articles', id: '123', role: 'edit' }
|
|
21
|
+
* `/admin/articles/123/comments/456/edit` → { slug: 'articles/123/comments', id: '456', role: 'edit' }
|
|
22
|
+
* `/admin/articles/123/comments` → null (no trailing /edit or /view)
|
|
23
|
+
* `/admin/articles/123/comments/create` → null (terminal token isn't edit|view)
|
|
22
24
|
* `/site/articles/123/edit` → null (basePath mismatch when basePath='/admin')
|
|
23
25
|
*/
|
|
24
|
-
|
|
26
|
+
|
|
27
|
+
/** Page roles `parseRecordPageUrl` recognizes. `'edit'` and `'view'`
|
|
28
|
+
* are the two record-scoped page roles where collab and other
|
|
29
|
+
* record-bound plugins want to mount their per-record wrapper. */
|
|
30
|
+
export type RecordPageRole = 'edit' | 'view'
|
|
31
|
+
|
|
32
|
+
export interface RecordPageIdentity {
|
|
25
33
|
resourceSlug: string
|
|
26
34
|
recordId: string
|
|
35
|
+
/** Which terminal URL segment matched — `'edit'` for the writable edit
|
|
36
|
+
* page, `'view'` for the read-only view page. Lets the gate decide per
|
|
37
|
+
* resource whether collab activates on this role (defaults to `'edit'`
|
|
38
|
+
* only; resources opt into `'view'` for presence-only experiences). */
|
|
39
|
+
role: RecordPageRole
|
|
27
40
|
}
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
const RECOGNIZED_ROLES: ReadonlyArray<RecordPageRole> = ['edit', 'view']
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Parse a pilotiq URL into a `{ slug, id, role }` identity. Returns
|
|
46
|
+
* `null` for any URL that isn't a record-edit or record-view page.
|
|
47
|
+
*/
|
|
48
|
+
export function parseRecordPageUrl(
|
|
30
49
|
currentPath: string,
|
|
31
50
|
basePath: string,
|
|
32
|
-
):
|
|
51
|
+
): RecordPageIdentity | null {
|
|
33
52
|
if (!currentPath) return null
|
|
34
53
|
// Normalise — trailing slashes on the URL or trailing slashes on
|
|
35
54
|
// basePath would otherwise reject perfectly valid matches.
|
|
@@ -42,7 +61,8 @@ export function parseRecordEditUrl(
|
|
|
42
61
|
const parts = tail.split('/').filter(Boolean)
|
|
43
62
|
|
|
44
63
|
if (parts.length < 3) return null
|
|
45
|
-
|
|
64
|
+
const terminal = parts[parts.length - 1]!
|
|
65
|
+
if (!RECOGNIZED_ROLES.includes(terminal as RecordPageRole)) return null
|
|
46
66
|
|
|
47
67
|
const recordId = parts[parts.length - 2]!
|
|
48
68
|
const slugParts = parts.slice(0, parts.length - 2)
|
|
@@ -51,5 +71,24 @@ export function parseRecordEditUrl(
|
|
|
51
71
|
return {
|
|
52
72
|
resourceSlug: slugParts.join('/'),
|
|
53
73
|
recordId,
|
|
74
|
+
role: terminal as RecordPageRole,
|
|
54
75
|
}
|
|
55
76
|
}
|
|
77
|
+
|
|
78
|
+
/** Legacy alias: parse a URL into an edit-only identity. Returns `null`
|
|
79
|
+
* for view URLs (and any non-edit URL). Kept for back-compat with the
|
|
80
|
+
* pre-`parseRecordPageUrl` public API; new code should call
|
|
81
|
+
* `parseRecordPageUrl` and branch on `role`. */
|
|
82
|
+
export interface RecordEditIdentity {
|
|
83
|
+
resourceSlug: string
|
|
84
|
+
recordId: string
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function parseRecordEditUrl(
|
|
88
|
+
currentPath: string,
|
|
89
|
+
basePath: string,
|
|
90
|
+
): RecordEditIdentity | null {
|
|
91
|
+
const identity = parseRecordPageUrl(currentPath, basePath)
|
|
92
|
+
if (!identity || identity.role !== 'edit') return null
|
|
93
|
+
return { resourceSlug: identity.resourceSlug, recordId: identity.recordId }
|
|
94
|
+
}
|