@anvilkit/contracts 0.1.18
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/LICENSE +21 -0
- package/dist/ai-section.cjs +18 -0
- package/dist/ai-section.d.cts +244 -0
- package/dist/ai-section.d.cts.map +1 -0
- package/dist/ai-section.d.ts +244 -0
- package/dist/ai-section.d.ts.map +1 -0
- package/dist/ai-section.js +1 -0
- package/dist/ai.cjs +18 -0
- package/dist/ai.d.cts +265 -0
- package/dist/ai.d.cts.map +1 -0
- package/dist/ai.d.ts +265 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +1 -0
- package/dist/assets.cjs +18 -0
- package/dist/assets.d.cts +32 -0
- package/dist/assets.d.cts.map +1 -0
- package/dist/assets.d.ts +32 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +1 -0
- package/dist/export.cjs +18 -0
- package/dist/export.d.cts +240 -0
- package/dist/export.d.cts.map +1 -0
- package/dist/export.d.ts +240 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +1 -0
- package/dist/index.cjs +18 -0
- package/dist/index.d.cts +45 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/ir.cjs +18 -0
- package/dist/ir.d.cts +269 -0
- package/dist/ir.d.cts.map +1 -0
- package/dist/ir.d.ts +269 -0
- package/dist/ir.d.ts.map +1 -0
- package/dist/ir.js +1 -0
- package/dist/page.cjs +18 -0
- package/dist/page.d.cts +197 -0
- package/dist/page.d.cts.map +1 -0
- package/dist/page.d.ts +197 -0
- package/dist/page.d.ts.map +1 -0
- package/dist/page.js +1 -0
- package/package.json +71 -0
package/dist/page.d.cts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file `<Studio>` Pages source contract.
|
|
3
|
+
*
|
|
4
|
+
* The `layer` sidebar module renders the host application's page list
|
|
5
|
+
* via this source. The host owns navigation — clicking a page row
|
|
6
|
+
* fires `onSelect` and the host is responsible for routing. v1 has no
|
|
7
|
+
* built-in router integration; the contract is intentionally minimal
|
|
8
|
+
* so any framework (Next.js App Router, Remix, custom) can adapt it.
|
|
9
|
+
*
|
|
10
|
+
* This is a pure type module — no runtime exports — so importing it
|
|
11
|
+
* adds zero bytes to the runtime bundle.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* A single page entry shown in the `layer/pages` sub-panel.
|
|
15
|
+
*
|
|
16
|
+
* `route` is a tagged flag, not a route string: it tells the sidebar
|
|
17
|
+
* to display the globe badge keyed `studio.module.layer.pages.routeBadge`.
|
|
18
|
+
* The actual URL lives on `path` and is interpreted by the host app.
|
|
19
|
+
*/
|
|
20
|
+
export interface StudioPage {
|
|
21
|
+
/** Stable id, unique within the source. */
|
|
22
|
+
readonly id: string;
|
|
23
|
+
/** Human-readable title shown in the row. */
|
|
24
|
+
readonly title: string;
|
|
25
|
+
/** Optional path (e.g. `"/about"`). Required for `route=true` rows. */
|
|
26
|
+
readonly path?: string;
|
|
27
|
+
/**
|
|
28
|
+
* `true` if this page corresponds to a public route (gets the
|
|
29
|
+
* globe badge); `false`/omitted for non-route content (templates,
|
|
30
|
+
* drafts, etc.).
|
|
31
|
+
*/
|
|
32
|
+
readonly route?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* `true` for the page currently loaded into the canvas. The host
|
|
35
|
+
* computes this from its routing state during {@link StudioPagesSource.list}
|
|
36
|
+
* and re-emits via `subscribe()` when the active page changes. The
|
|
37
|
+
* sidebar renders the row with the `--ak-studio-accent` background
|
|
38
|
+
* (PRD §6.2). Optional — sources that omit it always render every
|
|
39
|
+
* row inactive.
|
|
40
|
+
*/
|
|
41
|
+
readonly active?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Short meta/description text. Surfaced in the page settings
|
|
44
|
+
* dialog and (optionally) the SEO `<meta name="description">`
|
|
45
|
+
* fallback when {@link StudioPageSeo.metaDescription} is unset.
|
|
46
|
+
*/
|
|
47
|
+
readonly description?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Structured SEO block. When present, edited via the SEO section of
|
|
50
|
+
* the page settings dialog; when absent, the section is hidden.
|
|
51
|
+
*/
|
|
52
|
+
readonly seo?: StudioPageSeo;
|
|
53
|
+
/**
|
|
54
|
+
* Advisory only — {@link StudioPagesSource.list} order is authoritative
|
|
55
|
+
* for rendering. Hosts may use this for their own sorting/persistence.
|
|
56
|
+
*/
|
|
57
|
+
readonly order?: number;
|
|
58
|
+
/**
|
|
59
|
+
* `true` marks a page as non-renamable / non-deletable (e.g. `home`).
|
|
60
|
+
* Generalises the previous `isHome` heuristic — when set, rename and
|
|
61
|
+
* delete affordances are suppressed regardless of callback presence.
|
|
62
|
+
*/
|
|
63
|
+
readonly locked?: boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Input shape for {@link StudioPagesSource.onCreate}.
|
|
67
|
+
*
|
|
68
|
+
* Captures the `AddPageDialog` form values. `route` is optional
|
|
69
|
+
* because not every page is a public route.
|
|
70
|
+
*/
|
|
71
|
+
export interface StudioPageCreateInput {
|
|
72
|
+
readonly title: string;
|
|
73
|
+
readonly path: string;
|
|
74
|
+
readonly route?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Structured SEO metadata for a page. Every field is optional so the
|
|
78
|
+
* host can surface only what it persists; the settings dialog shows the
|
|
79
|
+
* full set when the source implements {@link StudioPagesSource.onUpdateSettings}.
|
|
80
|
+
*/
|
|
81
|
+
export interface StudioPageSeo {
|
|
82
|
+
readonly metaTitle?: string;
|
|
83
|
+
readonly metaDescription?: string;
|
|
84
|
+
readonly ogImage?: string;
|
|
85
|
+
readonly noindex?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Canonical URL for the page (`<link rel="canonical">`). Mirrors
|
|
88
|
+
* `root.props.seo.canonical` so the root↔sidecar projection
|
|
89
|
+
* (`pageRootSeoToStudioPageSeo` in `@anvilkit/core`) round-trips losslessly; the
|
|
90
|
+
* page-settings dialog does not edit it, so it passes through untouched.
|
|
91
|
+
*/
|
|
92
|
+
readonly canonical?: string;
|
|
93
|
+
}
|
|
94
|
+
/** Input shape for {@link StudioPagesSource.onRename}. */
|
|
95
|
+
export interface StudioPageRenameInput {
|
|
96
|
+
readonly id: string;
|
|
97
|
+
readonly title: string;
|
|
98
|
+
readonly path?: string;
|
|
99
|
+
}
|
|
100
|
+
/** Input shape for {@link StudioPagesSource.onReorder}. */
|
|
101
|
+
export interface StudioPageReorderInput {
|
|
102
|
+
readonly id: string;
|
|
103
|
+
readonly toIndex: number;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Input shape for {@link StudioPagesSource.onUpdateSettings}.
|
|
107
|
+
*
|
|
108
|
+
* Every editable field is optional — hosts that only persist a subset
|
|
109
|
+
* (e.g. title and SEO but not `description`) simply ignore the absent
|
|
110
|
+
* keys. The dialog sends only fields the user changed.
|
|
111
|
+
*/
|
|
112
|
+
export interface StudioPageSettingsInput {
|
|
113
|
+
readonly id: string;
|
|
114
|
+
readonly title?: string;
|
|
115
|
+
readonly path?: string;
|
|
116
|
+
readonly route?: boolean;
|
|
117
|
+
readonly description?: string;
|
|
118
|
+
readonly seo?: StudioPageSeo;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Pages source contract. The host application supplies one of these
|
|
122
|
+
* via the `<Studio>` `pages` prop. When omitted, the `layer/pages`
|
|
123
|
+
* sub-panel renders the empty state keyed
|
|
124
|
+
* `studio.module.layer.pages.empty`.
|
|
125
|
+
*
|
|
126
|
+
* `subscribe` is optional: sources backed by reactive stores wire
|
|
127
|
+
* live updates by calling the listener; static fixtures can omit it
|
|
128
|
+
* and rely on the sidebar's pull-on-mount semantics.
|
|
129
|
+
*
|
|
130
|
+
* ### Capability gating
|
|
131
|
+
*
|
|
132
|
+
* Every callback below is **optional**. The sidebar uses capability
|
|
133
|
+
* detection — "is the callback defined?" — to decide whether to render
|
|
134
|
+
* the matching affordance. A host that implements `onRename` gets the
|
|
135
|
+
* inline rename input; a host that doesn't gets a plain row. The
|
|
136
|
+
* existing `onCreate` / `subscribe?` gating is the precedent.
|
|
137
|
+
*
|
|
138
|
+
* ### Data-flow rule (PRD §3.3)
|
|
139
|
+
*
|
|
140
|
+
* **No optimistic mutation in core.** Every callback resolves → host
|
|
141
|
+
* mutates its registry → host invokes the {@link subscribe} listener →
|
|
142
|
+
* the panel re-runs {@link list}. The single documented exception is
|
|
143
|
+
* {@link onDuplicate}: it may return the created page so the UI can
|
|
144
|
+
* pre-select it before the refresh round-trips.
|
|
145
|
+
*/
|
|
146
|
+
export interface StudioPagesSource {
|
|
147
|
+
/** Return the current page list. May be sync or async. */
|
|
148
|
+
list(): readonly StudioPage[] | Promise<readonly StudioPage[]>;
|
|
149
|
+
/**
|
|
150
|
+
* Optional subscription. When set, the sidebar calls it on mount
|
|
151
|
+
* with a listener and re-runs `list()` whenever the listener fires.
|
|
152
|
+
* Returns an `unsubscribe` cleanup.
|
|
153
|
+
*/
|
|
154
|
+
subscribe?(listener: () => void): () => void;
|
|
155
|
+
/** Fired when a page row is clicked. Host routes to that page. */
|
|
156
|
+
onSelect?(pageId: string): void;
|
|
157
|
+
/**
|
|
158
|
+
* Fired when the `+` add-page dialog is submitted. Host creates
|
|
159
|
+
* the page and (optionally) navigates to it. Async result is
|
|
160
|
+
* awaited by the dialog so it can show a pending state.
|
|
161
|
+
*/
|
|
162
|
+
onCreate?(input: StudioPageCreateInput): void | Promise<void>;
|
|
163
|
+
/**
|
|
164
|
+
* Rename / re-path a page. The inline rename affordance is hidden
|
|
165
|
+
* when this callback is undefined OR when {@link StudioPage.locked}
|
|
166
|
+
* is `true` on the target row.
|
|
167
|
+
*/
|
|
168
|
+
onRename?(input: StudioPageRenameInput): void | Promise<void>;
|
|
169
|
+
/**
|
|
170
|
+
* Delete a page. The delete menu item + confirm dialog are hidden
|
|
171
|
+
* when this callback is undefined OR when {@link StudioPage.locked}
|
|
172
|
+
* is `true` on the target row.
|
|
173
|
+
*/
|
|
174
|
+
onDelete?(pageId: string): void | Promise<void>;
|
|
175
|
+
/**
|
|
176
|
+
* Duplicate a page. Hidden when undefined.
|
|
177
|
+
*
|
|
178
|
+
* **Optimistic-pre-select exception (PRD §3.3):** the host may
|
|
179
|
+
* resolve with the created {@link StudioPage} so the UI can pre-
|
|
180
|
+
* select it before the standard `subscribe → list()` refresh
|
|
181
|
+
* round-trips. Returning `void` is also valid — the row simply
|
|
182
|
+
* appears once the host's `subscribe` listener fires.
|
|
183
|
+
*/
|
|
184
|
+
onDuplicate?(pageId: string): void | Promise<StudioPage | void>;
|
|
185
|
+
/**
|
|
186
|
+
* Reorder a page to a new index. Drag handles are inert when this
|
|
187
|
+
* callback is undefined.
|
|
188
|
+
*/
|
|
189
|
+
onReorder?(input: StudioPageReorderInput): void | Promise<void>;
|
|
190
|
+
/**
|
|
191
|
+
* Update page settings + SEO. The settings menu item is hidden
|
|
192
|
+
* when this callback is undefined; the SEO section inside the
|
|
193
|
+
* dialog follows the same gate.
|
|
194
|
+
*/
|
|
195
|
+
onUpdateSettings?(input: StudioPageSettingsInput): void | Promise<void>;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=page.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.d.cts","sourceRoot":"","sources":["../src/page.ts"],"names":[],"mappings":"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"}
|
package/dist/page.d.ts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file `<Studio>` Pages source contract.
|
|
3
|
+
*
|
|
4
|
+
* The `layer` sidebar module renders the host application's page list
|
|
5
|
+
* via this source. The host owns navigation — clicking a page row
|
|
6
|
+
* fires `onSelect` and the host is responsible for routing. v1 has no
|
|
7
|
+
* built-in router integration; the contract is intentionally minimal
|
|
8
|
+
* so any framework (Next.js App Router, Remix, custom) can adapt it.
|
|
9
|
+
*
|
|
10
|
+
* This is a pure type module — no runtime exports — so importing it
|
|
11
|
+
* adds zero bytes to the runtime bundle.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* A single page entry shown in the `layer/pages` sub-panel.
|
|
15
|
+
*
|
|
16
|
+
* `route` is a tagged flag, not a route string: it tells the sidebar
|
|
17
|
+
* to display the globe badge keyed `studio.module.layer.pages.routeBadge`.
|
|
18
|
+
* The actual URL lives on `path` and is interpreted by the host app.
|
|
19
|
+
*/
|
|
20
|
+
export interface StudioPage {
|
|
21
|
+
/** Stable id, unique within the source. */
|
|
22
|
+
readonly id: string;
|
|
23
|
+
/** Human-readable title shown in the row. */
|
|
24
|
+
readonly title: string;
|
|
25
|
+
/** Optional path (e.g. `"/about"`). Required for `route=true` rows. */
|
|
26
|
+
readonly path?: string;
|
|
27
|
+
/**
|
|
28
|
+
* `true` if this page corresponds to a public route (gets the
|
|
29
|
+
* globe badge); `false`/omitted for non-route content (templates,
|
|
30
|
+
* drafts, etc.).
|
|
31
|
+
*/
|
|
32
|
+
readonly route?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* `true` for the page currently loaded into the canvas. The host
|
|
35
|
+
* computes this from its routing state during {@link StudioPagesSource.list}
|
|
36
|
+
* and re-emits via `subscribe()` when the active page changes. The
|
|
37
|
+
* sidebar renders the row with the `--ak-studio-accent` background
|
|
38
|
+
* (PRD §6.2). Optional — sources that omit it always render every
|
|
39
|
+
* row inactive.
|
|
40
|
+
*/
|
|
41
|
+
readonly active?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Short meta/description text. Surfaced in the page settings
|
|
44
|
+
* dialog and (optionally) the SEO `<meta name="description">`
|
|
45
|
+
* fallback when {@link StudioPageSeo.metaDescription} is unset.
|
|
46
|
+
*/
|
|
47
|
+
readonly description?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Structured SEO block. When present, edited via the SEO section of
|
|
50
|
+
* the page settings dialog; when absent, the section is hidden.
|
|
51
|
+
*/
|
|
52
|
+
readonly seo?: StudioPageSeo;
|
|
53
|
+
/**
|
|
54
|
+
* Advisory only — {@link StudioPagesSource.list} order is authoritative
|
|
55
|
+
* for rendering. Hosts may use this for their own sorting/persistence.
|
|
56
|
+
*/
|
|
57
|
+
readonly order?: number;
|
|
58
|
+
/**
|
|
59
|
+
* `true` marks a page as non-renamable / non-deletable (e.g. `home`).
|
|
60
|
+
* Generalises the previous `isHome` heuristic — when set, rename and
|
|
61
|
+
* delete affordances are suppressed regardless of callback presence.
|
|
62
|
+
*/
|
|
63
|
+
readonly locked?: boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Input shape for {@link StudioPagesSource.onCreate}.
|
|
67
|
+
*
|
|
68
|
+
* Captures the `AddPageDialog` form values. `route` is optional
|
|
69
|
+
* because not every page is a public route.
|
|
70
|
+
*/
|
|
71
|
+
export interface StudioPageCreateInput {
|
|
72
|
+
readonly title: string;
|
|
73
|
+
readonly path: string;
|
|
74
|
+
readonly route?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Structured SEO metadata for a page. Every field is optional so the
|
|
78
|
+
* host can surface only what it persists; the settings dialog shows the
|
|
79
|
+
* full set when the source implements {@link StudioPagesSource.onUpdateSettings}.
|
|
80
|
+
*/
|
|
81
|
+
export interface StudioPageSeo {
|
|
82
|
+
readonly metaTitle?: string;
|
|
83
|
+
readonly metaDescription?: string;
|
|
84
|
+
readonly ogImage?: string;
|
|
85
|
+
readonly noindex?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Canonical URL for the page (`<link rel="canonical">`). Mirrors
|
|
88
|
+
* `root.props.seo.canonical` so the root↔sidecar projection
|
|
89
|
+
* (`pageRootSeoToStudioPageSeo` in `@anvilkit/core`) round-trips losslessly; the
|
|
90
|
+
* page-settings dialog does not edit it, so it passes through untouched.
|
|
91
|
+
*/
|
|
92
|
+
readonly canonical?: string;
|
|
93
|
+
}
|
|
94
|
+
/** Input shape for {@link StudioPagesSource.onRename}. */
|
|
95
|
+
export interface StudioPageRenameInput {
|
|
96
|
+
readonly id: string;
|
|
97
|
+
readonly title: string;
|
|
98
|
+
readonly path?: string;
|
|
99
|
+
}
|
|
100
|
+
/** Input shape for {@link StudioPagesSource.onReorder}. */
|
|
101
|
+
export interface StudioPageReorderInput {
|
|
102
|
+
readonly id: string;
|
|
103
|
+
readonly toIndex: number;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Input shape for {@link StudioPagesSource.onUpdateSettings}.
|
|
107
|
+
*
|
|
108
|
+
* Every editable field is optional — hosts that only persist a subset
|
|
109
|
+
* (e.g. title and SEO but not `description`) simply ignore the absent
|
|
110
|
+
* keys. The dialog sends only fields the user changed.
|
|
111
|
+
*/
|
|
112
|
+
export interface StudioPageSettingsInput {
|
|
113
|
+
readonly id: string;
|
|
114
|
+
readonly title?: string;
|
|
115
|
+
readonly path?: string;
|
|
116
|
+
readonly route?: boolean;
|
|
117
|
+
readonly description?: string;
|
|
118
|
+
readonly seo?: StudioPageSeo;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Pages source contract. The host application supplies one of these
|
|
122
|
+
* via the `<Studio>` `pages` prop. When omitted, the `layer/pages`
|
|
123
|
+
* sub-panel renders the empty state keyed
|
|
124
|
+
* `studio.module.layer.pages.empty`.
|
|
125
|
+
*
|
|
126
|
+
* `subscribe` is optional: sources backed by reactive stores wire
|
|
127
|
+
* live updates by calling the listener; static fixtures can omit it
|
|
128
|
+
* and rely on the sidebar's pull-on-mount semantics.
|
|
129
|
+
*
|
|
130
|
+
* ### Capability gating
|
|
131
|
+
*
|
|
132
|
+
* Every callback below is **optional**. The sidebar uses capability
|
|
133
|
+
* detection — "is the callback defined?" — to decide whether to render
|
|
134
|
+
* the matching affordance. A host that implements `onRename` gets the
|
|
135
|
+
* inline rename input; a host that doesn't gets a plain row. The
|
|
136
|
+
* existing `onCreate` / `subscribe?` gating is the precedent.
|
|
137
|
+
*
|
|
138
|
+
* ### Data-flow rule (PRD §3.3)
|
|
139
|
+
*
|
|
140
|
+
* **No optimistic mutation in core.** Every callback resolves → host
|
|
141
|
+
* mutates its registry → host invokes the {@link subscribe} listener →
|
|
142
|
+
* the panel re-runs {@link list}. The single documented exception is
|
|
143
|
+
* {@link onDuplicate}: it may return the created page so the UI can
|
|
144
|
+
* pre-select it before the refresh round-trips.
|
|
145
|
+
*/
|
|
146
|
+
export interface StudioPagesSource {
|
|
147
|
+
/** Return the current page list. May be sync or async. */
|
|
148
|
+
list(): readonly StudioPage[] | Promise<readonly StudioPage[]>;
|
|
149
|
+
/**
|
|
150
|
+
* Optional subscription. When set, the sidebar calls it on mount
|
|
151
|
+
* with a listener and re-runs `list()` whenever the listener fires.
|
|
152
|
+
* Returns an `unsubscribe` cleanup.
|
|
153
|
+
*/
|
|
154
|
+
subscribe?(listener: () => void): () => void;
|
|
155
|
+
/** Fired when a page row is clicked. Host routes to that page. */
|
|
156
|
+
onSelect?(pageId: string): void;
|
|
157
|
+
/**
|
|
158
|
+
* Fired when the `+` add-page dialog is submitted. Host creates
|
|
159
|
+
* the page and (optionally) navigates to it. Async result is
|
|
160
|
+
* awaited by the dialog so it can show a pending state.
|
|
161
|
+
*/
|
|
162
|
+
onCreate?(input: StudioPageCreateInput): void | Promise<void>;
|
|
163
|
+
/**
|
|
164
|
+
* Rename / re-path a page. The inline rename affordance is hidden
|
|
165
|
+
* when this callback is undefined OR when {@link StudioPage.locked}
|
|
166
|
+
* is `true` on the target row.
|
|
167
|
+
*/
|
|
168
|
+
onRename?(input: StudioPageRenameInput): void | Promise<void>;
|
|
169
|
+
/**
|
|
170
|
+
* Delete a page. The delete menu item + confirm dialog are hidden
|
|
171
|
+
* when this callback is undefined OR when {@link StudioPage.locked}
|
|
172
|
+
* is `true` on the target row.
|
|
173
|
+
*/
|
|
174
|
+
onDelete?(pageId: string): void | Promise<void>;
|
|
175
|
+
/**
|
|
176
|
+
* Duplicate a page. Hidden when undefined.
|
|
177
|
+
*
|
|
178
|
+
* **Optimistic-pre-select exception (PRD §3.3):** the host may
|
|
179
|
+
* resolve with the created {@link StudioPage} so the UI can pre-
|
|
180
|
+
* select it before the standard `subscribe → list()` refresh
|
|
181
|
+
* round-trips. Returning `void` is also valid — the row simply
|
|
182
|
+
* appears once the host's `subscribe` listener fires.
|
|
183
|
+
*/
|
|
184
|
+
onDuplicate?(pageId: string): void | Promise<StudioPage | void>;
|
|
185
|
+
/**
|
|
186
|
+
* Reorder a page to a new index. Drag handles are inert when this
|
|
187
|
+
* callback is undefined.
|
|
188
|
+
*/
|
|
189
|
+
onReorder?(input: StudioPageReorderInput): void | Promise<void>;
|
|
190
|
+
/**
|
|
191
|
+
* Update page settings + SEO. The settings menu item is hidden
|
|
192
|
+
* when this callback is undefined; the SEO section inside the
|
|
193
|
+
* dialog follows the same gate.
|
|
194
|
+
*/
|
|
195
|
+
onUpdateSettings?(input: StudioPageSettingsInput): void | Promise<void>;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../src/page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IAC1B,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,0DAA0D;AAC1D,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,2DAA2D;AAC3D,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,iBAAiB;IACjC,0DAA0D;IAC1D,IAAI,IAAI,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IAC/D;;;;OAIG;IACH,SAAS,CAAC,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC7C,kEAAkE;IAClE,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D;;;;OAIG;IACH,QAAQ,CAAC,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D;;;;OAIG;IACH,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD;;;;;;;;OAQG;IACH,WAAW,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAChE;;;OAGG;IACH,SAAS,CAAC,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE;;;;OAIG;IACH,gBAAgB,CAAC,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE"}
|
package/dist/page.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@anvilkit/contracts",
|
|
3
|
+
"version": "0.1.18",
|
|
4
|
+
"description": "Shared type-only contracts — Page IR, AI generation, section patches, export formats, pages source, and asset resolution — consumed by @anvilkit/core and the headless packages.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@puckeditor/core": "^0.22.0"
|
|
31
|
+
},
|
|
32
|
+
"peerDependenciesMeta": {
|
|
33
|
+
"@puckeditor/core": {
|
|
34
|
+
"optional": false
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@puckeditor/core": "^0.22.0",
|
|
39
|
+
"@rslib/core": "^0.23.0",
|
|
40
|
+
"@types/node": "^26.0.1",
|
|
41
|
+
"esbuild": "^0.28.0",
|
|
42
|
+
"madge": "^8.0.0",
|
|
43
|
+
"publint": "^0.3.21",
|
|
44
|
+
"typedoc": "^0.28.19",
|
|
45
|
+
"typedoc-plugin-markdown": "^4.11.2",
|
|
46
|
+
"typescript": "6.0.3",
|
|
47
|
+
"vitest": "^4.1.9",
|
|
48
|
+
"@anvilkit/biome-config": "0.0.1",
|
|
49
|
+
"@anvilkit/vitest-config": "0.0.1",
|
|
50
|
+
"@anvilkit/typescript-config": "0.0.1"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "rslib build",
|
|
54
|
+
"dev": "rslib build --watch",
|
|
55
|
+
"lint": "pnpm exec biome lint package.json tsconfig.json rslib.config.ts vitest.config.ts src",
|
|
56
|
+
"format": "pnpm exec biome check --write package.json tsconfig.json rslib.config.ts vitest.config.ts src",
|
|
57
|
+
"typecheck": "tsc --noEmit",
|
|
58
|
+
"test": "vitest run",
|
|
59
|
+
"test:watch": "vitest",
|
|
60
|
+
"publint": "node ./scripts/check-publint.mjs",
|
|
61
|
+
"check:publint": "node ./scripts/check-publint.mjs",
|
|
62
|
+
"check:circular": "madge --circular --extensions ts src/",
|
|
63
|
+
"check:react-free-runtime": "node ./scripts/check-react-free.mjs",
|
|
64
|
+
"check:peer-deps": "node ./scripts/check-peer-deps.mjs",
|
|
65
|
+
"check:bundle-budget": "node ./scripts/check-bundle-budget.mjs",
|
|
66
|
+
"check:api-snapshot": "node ./scripts/check-api-snapshot.mjs",
|
|
67
|
+
"check:all": "pnpm check:publint && pnpm check:circular && pnpm check:react-free-runtime && pnpm check:peer-deps && pnpm check:bundle-budget && pnpm check:api-snapshot",
|
|
68
|
+
"update:api-snapshot": "node ./scripts/check-api-snapshot.mjs --update",
|
|
69
|
+
"size": "size-limit"
|
|
70
|
+
}
|
|
71
|
+
}
|