@happyvertical/smrt-content 0.51.39 → 0.53.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/AGENTS.md +6 -0
- package/README.md +86 -0
- package/dist/body-format.d.ts +104 -0
- package/dist/body-format.d.ts.map +1 -1
- package/dist/body-format.js +439 -48
- package/dist/body-format.js.map +1 -1
- package/dist/chunks/content-query-C6RcW8V_.js +4131 -0
- package/dist/chunks/content-query-C6RcW8V_.js.map +1 -0
- package/dist/chunks/{content-versions-CvOoDLSK.js → content-versions-HUeMI1TV.js} +2 -2
- package/dist/chunks/{content-versions-CvOoDLSK.js.map → content-versions-HUeMI1TV.js.map} +1 -1
- package/dist/chunks/{contents-BB7RIBx2.js → contents-CHa5soKR.js} +4 -6
- package/dist/chunks/contents-CHa5soKR.js.map +1 -0
- package/dist/content-query.d.ts.map +1 -1
- package/dist/content.d.ts +13 -1
- package/dist/content.d.ts.map +1 -1
- package/dist/contents.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/manifest.json +113 -23
- package/dist/server/content-list-data-surface.d.ts +1 -1
- package/dist/server/content-list-data-surface.d.ts.map +1 -1
- package/dist/server.js +3 -3
- package/dist/server.js.map +1 -1
- package/dist/smrt-knowledge.json +92 -10
- package/dist/svelte/components/ContentBodyEditor.svelte +898 -38
- package/dist/svelte/components/ContentBodyEditor.svelte.d.ts +67 -0
- package/dist/svelte/components/ContentBodyEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentBodyRenderer.svelte +36 -11
- package/dist/svelte/components/ContentBodyRenderer.svelte.d.ts +2 -0
- package/dist/svelte/components/ContentBodyRenderer.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentClaimAuditTool.svelte +45 -2
- package/dist/svelte/components/ContentCorrectionsTool.svelte +24 -2
- package/dist/svelte/components/ContentEditor.svelte +67 -17
- package/dist/svelte/components/ContentEditor.svelte.d.ts +12 -0
- package/dist/svelte/components/ContentEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentGovernancePanel.svelte +4 -2
- package/dist/svelte/components/ContentMetadataFields.svelte +141 -51
- package/dist/svelte/components/ContentMetadataFields.svelte.d.ts +20 -0
- package/dist/svelte/components/ContentMetadataFields.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentPictureDrawer.svelte +611 -0
- package/dist/svelte/components/ContentPictureDrawer.svelte.d.ts +68 -0
- package/dist/svelte/components/ContentPictureDrawer.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ContentReviewStatusTray.svelte +2 -2
- package/dist/svelte/components/ContentStatusFields.svelte +85 -38
- package/dist/svelte/components/ContentStatusFields.svelte.d.ts +10 -0
- package/dist/svelte/components/ContentStatusFields.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentTitleField.svelte +109 -12
- package/dist/svelte/components/ContentTitleField.svelte.d.ts +12 -0
- package/dist/svelte/components/ContentTitleField.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentTransparencyReport.svelte +3 -1
- package/dist/svelte/components/ContentTransparencyTool.svelte +18 -3
- package/dist/svelte/components/ContentVersionsTool.svelte +26 -2
- package/dist/svelte/components/content-field-mode.d.ts +20 -0
- package/dist/svelte/components/content-field-mode.d.ts.map +1 -0
- package/dist/svelte/components/content-field-mode.js +26 -0
- package/dist/svelte/content-editor-media.d.ts +14 -0
- package/dist/svelte/content-editor-media.d.ts.map +1 -1
- package/dist/svelte/content-editor-media.js +41 -0
- package/dist/svelte/content-editor-state.svelte.d.ts +17 -0
- package/dist/svelte/content-editor-state.svelte.d.ts.map +1 -1
- package/dist/svelte/content-editor-state.svelte.js +46 -0
- package/dist/svelte/i18n.editor.d.ts +49 -0
- package/dist/svelte/i18n.editor.d.ts.map +1 -1
- package/dist/svelte/i18n.editor.js +53 -1
- package/dist/svelte/index.d.ts +10 -5
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +5 -3
- package/package.json +27 -25
- package/dist/chunks/content-query-DPJCcD1V.js +0 -4092
- package/dist/chunks/content-query-DPJCcD1V.js.map +0 -1
- package/dist/chunks/contents-BB7RIBx2.js.map +0 -1
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { Input, Select } from '@happyvertical/smrt-ui/forms';
|
|
2
|
+
import { FormGroup, Input, Select } from '@happyvertical/smrt-ui/forms';
|
|
3
3
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
4
4
|
import { M } from '../i18n.editor.js';
|
|
5
|
+
import {
|
|
6
|
+
type ContentFieldMode,
|
|
7
|
+
type ContentStatusFieldName,
|
|
8
|
+
FULL_STATUS_FIELDS,
|
|
9
|
+
resolveContentFields,
|
|
10
|
+
SIMPLE_STATUS_FIELDS,
|
|
11
|
+
} from './content-field-mode.js';
|
|
5
12
|
|
|
6
13
|
const { t } = useI18n();
|
|
7
14
|
|
|
@@ -16,52 +23,84 @@ export interface ContentStatusFieldData {
|
|
|
16
23
|
export interface Props {
|
|
17
24
|
/** Current status field values. */
|
|
18
25
|
data: ContentStatusFieldData;
|
|
26
|
+
/**
|
|
27
|
+
* `full` (default) shows Type, State, Status and Published; `simple` shows
|
|
28
|
+
* Status and an optional Publish date with plain labels.
|
|
29
|
+
*/
|
|
30
|
+
mode?: ContentFieldMode;
|
|
31
|
+
/** Explicit allow-list of fields; overrides the mode's choice. */
|
|
32
|
+
fields?: readonly ContentStatusFieldName[];
|
|
33
|
+
/** Prefix for field DOM ids, unique per editor on the page (default `content`). */
|
|
34
|
+
idPrefix?: string;
|
|
19
35
|
/** Invoked when the user modifies any status field. */
|
|
20
36
|
onChange?: (change: Record<string, unknown>) => void;
|
|
21
37
|
}
|
|
22
38
|
|
|
23
|
-
let {
|
|
39
|
+
let {
|
|
40
|
+
data,
|
|
41
|
+
mode = 'full',
|
|
42
|
+
fields = undefined,
|
|
43
|
+
idPrefix = 'content',
|
|
44
|
+
onChange = undefined,
|
|
45
|
+
}: Props = $props();
|
|
46
|
+
|
|
47
|
+
const simple = $derived(mode === 'simple');
|
|
48
|
+
const shown = $derived(
|
|
49
|
+
resolveContentFields(mode, fields, SIMPLE_STATUS_FIELDS, FULL_STATUS_FIELDS),
|
|
50
|
+
);
|
|
51
|
+
const publishLabel = $derived(
|
|
52
|
+
simple
|
|
53
|
+
? t(M['content.content_fields.optional'], {
|
|
54
|
+
label: t(M['content.content_fields.publish_date']),
|
|
55
|
+
})
|
|
56
|
+
: t(M['content.content_fields.published']),
|
|
57
|
+
);
|
|
24
58
|
|
|
25
59
|
function updateField(key: string, value: unknown) {
|
|
26
60
|
onChange?.({ [key]: value });
|
|
27
61
|
}
|
|
28
62
|
</script>
|
|
29
63
|
|
|
30
|
-
<div class="content-status-fields">
|
|
31
|
-
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
<div class="content-status-fields" class:simple>
|
|
65
|
+
{#if shown.has('type')}
|
|
66
|
+
<FormGroup label={t(M['content.content_fields.type'])} id="{idPrefix}-type">
|
|
67
|
+
<Select name="type" value={data.type || 'article'} onchange={(event) => updateField('type', event.currentTarget.value)}>
|
|
68
|
+
<option value="article">Article</option>
|
|
69
|
+
<option value="document">Document</option>
|
|
70
|
+
<option value="mirror">Mirror</option>
|
|
71
|
+
<option value="video-segment">{t(M['content.content_status_fields.video_segment'])}</option>
|
|
72
|
+
</Select>
|
|
73
|
+
</FormGroup>
|
|
74
|
+
{/if}
|
|
75
|
+
{#if shown.has('state')}
|
|
76
|
+
<FormGroup label={t(M['content.content_fields.state'])} id="{idPrefix}-state">
|
|
77
|
+
<Select name="state" value={data.state || 'active'} onchange={(event) => updateField('state', event.currentTarget.value)}>
|
|
78
|
+
<option value="active">Active</option>
|
|
79
|
+
<option value="highlighted">Highlighted</option>
|
|
80
|
+
<option value="deprecated">Deprecated</option>
|
|
81
|
+
</Select>
|
|
82
|
+
</FormGroup>
|
|
83
|
+
{/if}
|
|
84
|
+
{#if shown.has('status')}
|
|
85
|
+
<FormGroup label={t(M['content.content_fields.status'])} id="{idPrefix}-status">
|
|
86
|
+
<Select name="status" value={data.status || 'draft'} onchange={(event) => updateField('status', event.currentTarget.value)}>
|
|
87
|
+
<option value="draft">{t(M['content.content_fields.status_draft'])}</option>
|
|
88
|
+
<option value="review">{t(M['content.content_fields.status_review'])}</option>
|
|
89
|
+
<option value="published">{t(M['content.content_fields.status_published'])}</option>
|
|
90
|
+
<option value="archived">{t(M['content.content_fields.status_archived'])}</option>
|
|
91
|
+
</Select>
|
|
92
|
+
</FormGroup>
|
|
93
|
+
{/if}
|
|
94
|
+
{#if shown.has('publish_date')}
|
|
95
|
+
<FormGroup label={publishLabel} id="{idPrefix}-publish-date">
|
|
96
|
+
<Input
|
|
97
|
+
name="publish_date"
|
|
98
|
+
type="datetime-local"
|
|
99
|
+
value={data.publish_date || ''}
|
|
100
|
+
onchange={(event) => updateField('publish_date', event.currentTarget.value)}
|
|
101
|
+
/>
|
|
102
|
+
</FormGroup>
|
|
103
|
+
{/if}
|
|
65
104
|
</div>
|
|
66
105
|
|
|
67
106
|
<style>
|
|
@@ -72,13 +111,21 @@ function updateField(key: string, value: unknown) {
|
|
|
72
111
|
gap: 0.75rem;
|
|
73
112
|
}
|
|
74
113
|
|
|
75
|
-
|
|
114
|
+
.content-status-fields :global(.form-group) {
|
|
76
115
|
display: grid;
|
|
77
116
|
gap: 0.35rem;
|
|
78
117
|
min-width: 8.5rem;
|
|
118
|
+
margin: 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.content-status-fields :global(.form-label) {
|
|
122
|
+
margin: 0;
|
|
79
123
|
color: var(--smrt-color-on-surface-variant);
|
|
80
124
|
font-size: var(--smrt-typography-label-medium-size, 0.75rem);
|
|
81
125
|
font-weight: var(--smrt-typography-weight-semibold, 600);
|
|
82
126
|
}
|
|
83
127
|
|
|
128
|
+
.content-status-fields.simple :global(.form-label) {
|
|
129
|
+
font-size: var(--smrt-typography-label-large-size, 0.875rem);
|
|
130
|
+
}
|
|
84
131
|
</style>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ContentFieldMode, type ContentStatusFieldName } from './content-field-mode.js';
|
|
1
2
|
export interface ContentStatusFieldData {
|
|
2
3
|
type?: string;
|
|
3
4
|
state?: string;
|
|
@@ -8,6 +9,15 @@ export interface ContentStatusFieldData {
|
|
|
8
9
|
export interface Props {
|
|
9
10
|
/** Current status field values. */
|
|
10
11
|
data: ContentStatusFieldData;
|
|
12
|
+
/**
|
|
13
|
+
* `full` (default) shows Type, State, Status and Published; `simple` shows
|
|
14
|
+
* Status and an optional Publish date with plain labels.
|
|
15
|
+
*/
|
|
16
|
+
mode?: ContentFieldMode;
|
|
17
|
+
/** Explicit allow-list of fields; overrides the mode's choice. */
|
|
18
|
+
fields?: readonly ContentStatusFieldName[];
|
|
19
|
+
/** Prefix for field DOM ids, unique per editor on the page (default `content`). */
|
|
20
|
+
idPrefix?: string;
|
|
11
21
|
/** Invoked when the user modifies any status field. */
|
|
12
22
|
onChange?: (change: Record<string, unknown>) => void;
|
|
13
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentStatusFields.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ContentStatusFields.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ContentStatusFields.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ContentStatusFields.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAI5B,MAAM,yBAAyB,CAAC;AAGjC,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,KAAK;IACpB,mCAAmC;IACnC,IAAI,EAAE,sBAAsB,CAAC;IAC7B;;;OAGG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,kEAAkE;IAClE,MAAM,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC3C,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACtD;AA6ED,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* ContentTitleField - a content item's title as a headline-style text field.
|
|
4
|
+
*
|
|
5
|
+
* The title wraps like a heading (a one-row textarea that grows with its
|
|
6
|
+
* text) but stays one line of text: Enter never adds a newline, and pasted
|
|
7
|
+
* line breaks become spaces. It is a labelled control (`label`, default
|
|
8
|
+
* "Title"), so it can sit inside the page's `<h1>` (smrt-ui PageHeader's
|
|
9
|
+
* `titleField`): the heading is then named by the title and the field keeps
|
|
10
|
+
* its own label. Inside a heading it takes the heading's type.
|
|
11
|
+
*
|
|
12
|
+
* Give it a `name` (or `id`) so a surrounding agent-operable form registers
|
|
13
|
+
* it like any smrt-ui control. Validation messages belong outside a heading:
|
|
14
|
+
* render the message beside it and point `describedBy` at it.
|
|
15
|
+
*/
|
|
16
|
+
import { Textarea } from '@happyvertical/smrt-ui/forms';
|
|
3
17
|
|
|
4
18
|
export interface Props {
|
|
5
19
|
/** Current title text value. */
|
|
@@ -8,6 +22,18 @@ export interface Props {
|
|
|
8
22
|
placeholder?: string;
|
|
9
23
|
/** Whether the title field must be filled before submission. */
|
|
10
24
|
required?: boolean;
|
|
25
|
+
/** Accessible name of the field. */
|
|
26
|
+
label?: string;
|
|
27
|
+
/** Form field name; also its identity for agent-operable forms. */
|
|
28
|
+
name?: string;
|
|
29
|
+
/** Element id. */
|
|
30
|
+
id?: string;
|
|
31
|
+
/** Marks the field invalid (e.g. an empty required title). */
|
|
32
|
+
invalid?: boolean;
|
|
33
|
+
/** Id(s) of the element(s) describing the field, e.g. its error message. */
|
|
34
|
+
describedBy?: string;
|
|
35
|
+
/** Whether the field is disabled. */
|
|
36
|
+
disabled?: boolean;
|
|
11
37
|
/** Invoked when the user modifies the title text. */
|
|
12
38
|
onChange?: (value: string) => void;
|
|
13
39
|
}
|
|
@@ -16,27 +42,80 @@ let {
|
|
|
16
42
|
value = '',
|
|
17
43
|
placeholder = 'Title',
|
|
18
44
|
required = false,
|
|
45
|
+
label = 'Title',
|
|
46
|
+
name = undefined,
|
|
47
|
+
id = undefined,
|
|
48
|
+
invalid = false,
|
|
49
|
+
describedBy = undefined,
|
|
50
|
+
disabled = false,
|
|
19
51
|
onChange = undefined,
|
|
20
52
|
}: Props = $props();
|
|
53
|
+
|
|
54
|
+
let field = $state<ReturnType<typeof Textarea> | null>(null);
|
|
55
|
+
|
|
56
|
+
function fitHeight() {
|
|
57
|
+
const element = field?.getElement();
|
|
58
|
+
if (!element) return;
|
|
59
|
+
element.style.height = 'auto';
|
|
60
|
+
element.style.height = `${element.scrollHeight}px`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
$effect(() => {
|
|
64
|
+
void value;
|
|
65
|
+
fitHeight();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
69
|
+
// One line of text: Enter neither adds a newline nor submits.
|
|
70
|
+
if (event.key === 'Enter' && !event.isComposing) event.preventDefault();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function handleInput(event: Event & { currentTarget: HTMLTextAreaElement }) {
|
|
74
|
+
const element = event.currentTarget;
|
|
75
|
+
const text = element.value.replace(/[\r\n]+/g, ' ');
|
|
76
|
+
if (text !== element.value) {
|
|
77
|
+
const caret = element.selectionStart;
|
|
78
|
+
element.value = text;
|
|
79
|
+
if (caret !== null) element.setSelectionRange(caret, caret);
|
|
80
|
+
}
|
|
81
|
+
fitHeight();
|
|
82
|
+
onChange?.(text);
|
|
83
|
+
}
|
|
21
84
|
</script>
|
|
22
85
|
|
|
23
|
-
<
|
|
24
|
-
|
|
86
|
+
<svelte:window onresize={fitHeight} />
|
|
87
|
+
|
|
88
|
+
<span class="content-title-field-shell">
|
|
89
|
+
<Textarea
|
|
90
|
+
bind:this={field}
|
|
25
91
|
class="content-title-field"
|
|
26
|
-
|
|
92
|
+
rows={1}
|
|
93
|
+
{id}
|
|
94
|
+
{name}
|
|
27
95
|
{placeholder}
|
|
28
96
|
{required}
|
|
97
|
+
{disabled}
|
|
98
|
+
aria-label={label}
|
|
99
|
+
aria-invalid={invalid ? 'true' : undefined}
|
|
100
|
+
aria-describedby={describedBy}
|
|
29
101
|
value={value || ''}
|
|
30
|
-
|
|
102
|
+
onkeydown={handleKeydown}
|
|
103
|
+
oninput={handleInput}
|
|
31
104
|
/>
|
|
32
|
-
</
|
|
105
|
+
</span>
|
|
33
106
|
|
|
34
107
|
<style>
|
|
108
|
+
.content-title-field-shell {
|
|
109
|
+
display: block;
|
|
110
|
+
}
|
|
111
|
+
|
|
35
112
|
.content-title-field-shell :global(.content-title-field) {
|
|
113
|
+
display: block;
|
|
36
114
|
width: 100%;
|
|
115
|
+
min-height: 0;
|
|
37
116
|
box-sizing: border-box;
|
|
38
117
|
border: 0;
|
|
39
|
-
border-radius:
|
|
118
|
+
border-radius: var(--smrt-radius-sm, 4px);
|
|
40
119
|
background: transparent;
|
|
41
120
|
color: var(--smrt-color-on-surface);
|
|
42
121
|
font: inherit;
|
|
@@ -44,19 +123,37 @@ let {
|
|
|
44
123
|
font-weight: var(--smrt-typography-weight-bold, 720);
|
|
45
124
|
line-height: 1.12;
|
|
46
125
|
letter-spacing: 0;
|
|
47
|
-
padding: 0;
|
|
126
|
+
padding: 0.1em 0.2em;
|
|
127
|
+
margin-inline: -0.2em;
|
|
128
|
+
resize: none;
|
|
129
|
+
overflow: hidden;
|
|
130
|
+
field-sizing: content;
|
|
131
|
+
transition: background-color 150ms;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Inside a heading, look like that heading. */
|
|
135
|
+
:global(:is(h1, h2, h3)) > .content-title-field-shell :global(.content-title-field) {
|
|
136
|
+
font: inherit;
|
|
137
|
+
letter-spacing: inherit;
|
|
48
138
|
}
|
|
49
139
|
|
|
50
140
|
.content-title-field-shell :global(.content-title-field)::placeholder {
|
|
51
141
|
color: color-mix(in srgb, var(--smrt-color-on-surface-variant) 70%, transparent);
|
|
52
142
|
}
|
|
53
143
|
|
|
54
|
-
|
|
55
|
-
|
|
144
|
+
/* Editable on hover and focus: a quiet field background, then an outline. */
|
|
145
|
+
.content-title-field-shell :global(.content-title-field):hover:not(:disabled) {
|
|
146
|
+
background: var(--smrt-color-surface-container-low, rgb(0 0 0 / 4%));
|
|
56
147
|
}
|
|
57
148
|
|
|
58
|
-
.content-title-field-shell :global(.content-title-field):focus
|
|
149
|
+
.content-title-field-shell :global(.content-title-field):focus {
|
|
59
150
|
outline: 2px solid var(--smrt-color-primary, #005ac1);
|
|
60
|
-
outline-offset:
|
|
151
|
+
outline-offset: 2px;
|
|
152
|
+
background: var(--smrt-color-surface-container-low, rgb(0 0 0 / 4%));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.content-title-field-shell :global(.content-title-field[aria-invalid='true']) {
|
|
156
|
+
outline: 2px solid var(--smrt-color-error, #b3261e);
|
|
157
|
+
outline-offset: 2px;
|
|
61
158
|
}
|
|
62
159
|
</style>
|
|
@@ -5,6 +5,18 @@ export interface Props {
|
|
|
5
5
|
placeholder?: string;
|
|
6
6
|
/** Whether the title field must be filled before submission. */
|
|
7
7
|
required?: boolean;
|
|
8
|
+
/** Accessible name of the field. */
|
|
9
|
+
label?: string;
|
|
10
|
+
/** Form field name; also its identity for agent-operable forms. */
|
|
11
|
+
name?: string;
|
|
12
|
+
/** Element id. */
|
|
13
|
+
id?: string;
|
|
14
|
+
/** Marks the field invalid (e.g. an empty required title). */
|
|
15
|
+
invalid?: boolean;
|
|
16
|
+
/** Id(s) of the element(s) describing the field, e.g. its error message. */
|
|
17
|
+
describedBy?: string;
|
|
18
|
+
/** Whether the field is disabled. */
|
|
19
|
+
disabled?: boolean;
|
|
8
20
|
/** Invoked when the user modifies the title text. */
|
|
9
21
|
onChange?: (value: string) => void;
|
|
10
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentTitleField.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ContentTitleField.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ContentTitleField.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ContentTitleField.svelte.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,KAAK;IACpB,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AA6DD,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
|
@@ -216,6 +216,8 @@ function getFactLabel(fact: {
|
|
|
216
216
|
|
|
217
217
|
<style>
|
|
218
218
|
.transparency-report {
|
|
219
|
+
container-type: inline-size;
|
|
220
|
+
container-name: transparency-report;
|
|
219
221
|
display: flex;
|
|
220
222
|
flex-direction: column;
|
|
221
223
|
gap: 1rem;
|
|
@@ -269,7 +271,7 @@ function getFactLabel(fact: {
|
|
|
269
271
|
gap: 1rem;
|
|
270
272
|
}
|
|
271
273
|
|
|
272
|
-
@
|
|
274
|
+
@container transparency-report (min-width: 56rem) {
|
|
273
275
|
.transparency-grid {
|
|
274
276
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
275
277
|
}
|
|
@@ -223,6 +223,13 @@ async function loadTransparency(contentIdToLoad = savedContentId) {
|
|
|
223
223
|
</div>
|
|
224
224
|
|
|
225
225
|
<style>
|
|
226
|
+
/* The tool lays itself out by its own width, not the viewport, so it
|
|
227
|
+
fits a full page, a side panel, the assistant dock or a phone. */
|
|
228
|
+
.governance-tool {
|
|
229
|
+
container-type: inline-size;
|
|
230
|
+
container-name: governance-tool;
|
|
231
|
+
}
|
|
232
|
+
|
|
226
233
|
.governance-tool,
|
|
227
234
|
.tool-list,
|
|
228
235
|
.tool-list-section,
|
|
@@ -235,14 +242,15 @@ async function loadTransparency(contentIdToLoad = savedContentId) {
|
|
|
235
242
|
.transparency-stats {
|
|
236
243
|
display: grid;
|
|
237
244
|
gap: 0.75rem;
|
|
238
|
-
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
|
245
|
+
grid-template-columns: repeat(auto-fit, minmax(min(120px, 100%), 1fr));
|
|
239
246
|
}
|
|
240
247
|
|
|
241
248
|
.transparency-stat,
|
|
242
249
|
.transparency-card,
|
|
243
250
|
.transparency-list-item {
|
|
244
|
-
background: var(--smrt-color-surface);
|
|
245
|
-
border: 1px solid var(--smrt-color-outline-variant);
|
|
251
|
+
background: var(--smrt-card-background, var(--smrt-color-surface));
|
|
252
|
+
border: var(--smrt-card-border, 1px solid var(--smrt-color-outline-variant));
|
|
253
|
+
box-shadow: var(--smrt-card-shadow, none);
|
|
246
254
|
border-radius: 0.75rem;
|
|
247
255
|
}
|
|
248
256
|
|
|
@@ -265,6 +273,7 @@ async function loadTransparency(contentIdToLoad = savedContentId) {
|
|
|
265
273
|
}
|
|
266
274
|
|
|
267
275
|
.transparency-list-item {
|
|
276
|
+
background: color-mix(in srgb, var(--smrt-color-on-surface) 6%, transparent);
|
|
268
277
|
padding: 0.7rem 0.8rem;
|
|
269
278
|
display: flex;
|
|
270
279
|
flex-direction: column;
|
|
@@ -316,4 +325,10 @@ async function loadTransparency(contentIdToLoad = savedContentId) {
|
|
|
316
325
|
color: var(--smrt-color-on-error-container);
|
|
317
326
|
font-size: var(--smrt-typography-body-medium-size, 0.9rem);
|
|
318
327
|
}
|
|
328
|
+
|
|
329
|
+
@container governance-tool (max-width: 30rem) {
|
|
330
|
+
.tool-card-header {
|
|
331
|
+
flex-wrap: wrap;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
319
334
|
</style>
|
|
@@ -241,6 +241,13 @@ async function restoreVersion(versionNumber: number) {
|
|
|
241
241
|
/>
|
|
242
242
|
|
|
243
243
|
<style>
|
|
244
|
+
/* The tool lays itself out by its own width, not the viewport, so it
|
|
245
|
+
fits a full page, a side panel, the assistant dock or a phone. */
|
|
246
|
+
.governance-tool {
|
|
247
|
+
container-type: inline-size;
|
|
248
|
+
container-name: governance-tool;
|
|
249
|
+
}
|
|
250
|
+
|
|
244
251
|
.governance-tool,
|
|
245
252
|
.tool-list,
|
|
246
253
|
.tool-card {
|
|
@@ -263,8 +270,9 @@ async function restoreVersion(versionNumber: number) {
|
|
|
263
270
|
}
|
|
264
271
|
|
|
265
272
|
.tool-card {
|
|
266
|
-
background: var(--smrt-color-surface);
|
|
267
|
-
border: 1px solid var(--smrt-color-outline-variant);
|
|
273
|
+
background: var(--smrt-card-background, var(--smrt-color-surface));
|
|
274
|
+
border: var(--smrt-card-border, 1px solid var(--smrt-color-outline-variant));
|
|
275
|
+
box-shadow: var(--smrt-card-shadow, none);
|
|
268
276
|
border-radius: 0.75rem;
|
|
269
277
|
padding: 0.85rem;
|
|
270
278
|
}
|
|
@@ -309,4 +317,20 @@ async function restoreVersion(versionNumber: number) {
|
|
|
309
317
|
background: color-mix(in srgb, var(--smrt-color-primary) 10%, transparent);
|
|
310
318
|
color: var(--smrt-color-on-primary-container);
|
|
311
319
|
}
|
|
320
|
+
|
|
321
|
+
@container governance-tool (max-width: 30rem) {
|
|
322
|
+
.tool-toolbar {
|
|
323
|
+
justify-content: stretch;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.tool-toolbar :global(button),
|
|
327
|
+
.tool-card-footer :global(button) {
|
|
328
|
+
width: 100%;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.tool-card-footer {
|
|
332
|
+
flex-direction: column;
|
|
333
|
+
align-items: stretch;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
312
336
|
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple vs full editor fields.
|
|
3
|
+
*
|
|
4
|
+
* `full` (the default) keeps every field and the long-standing labels.
|
|
5
|
+
* `simple` is for everyday editors — a title, the story, images, author,
|
|
6
|
+
* summary and tags: it hides Type, State, URL, File key (and, in
|
|
7
|
+
* ContentEditor, references), collapses the Details section, uses plain
|
|
8
|
+
* labels, and marks optional fields "(optional)". A `fields` allow-list
|
|
9
|
+
* overrides either mode's choice of fields.
|
|
10
|
+
*/
|
|
11
|
+
export type ContentFieldMode = 'simple' | 'full';
|
|
12
|
+
export type ContentStatusFieldName = 'type' | 'state' | 'status' | 'publish_date';
|
|
13
|
+
export type ContentMetadataFieldName = 'author' | 'description' | 'tags' | 'url' | 'fileKey';
|
|
14
|
+
export declare const SIMPLE_STATUS_FIELDS: readonly ContentStatusFieldName[];
|
|
15
|
+
export declare const FULL_STATUS_FIELDS: readonly ContentStatusFieldName[];
|
|
16
|
+
export declare const SIMPLE_METADATA_FIELDS: readonly ContentMetadataFieldName[];
|
|
17
|
+
export declare const FULL_METADATA_FIELDS: readonly ContentMetadataFieldName[];
|
|
18
|
+
/** The fields to render: an explicit allow-list wins over the mode. */
|
|
19
|
+
export declare function resolveContentFields<T extends string>(mode: ContentFieldMode, fields: readonly T[] | undefined, simple: readonly T[], full: readonly T[]): Set<T>;
|
|
20
|
+
//# sourceMappingURL=content-field-mode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-field-mode.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/content-field-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEjD,MAAM,MAAM,sBAAsB,GAC9B,MAAM,GACN,OAAO,GACP,QAAQ,GACR,cAAc,CAAC;AACnB,MAAM,MAAM,wBAAwB,GAChC,QAAQ,GACR,aAAa,GACb,MAAM,GACN,KAAK,GACL,SAAS,CAAC;AAEd,eAAO,MAAM,oBAAoB,EAAE,SAAS,sBAAsB,EAGjE,CAAC;AACF,eAAO,MAAM,kBAAkB,EAAE,SAAS,sBAAsB,EAK/D,CAAC;AACF,eAAO,MAAM,sBAAsB,EAAE,SAAS,wBAAwB,EAIrE,CAAC;AACF,eAAO,MAAM,oBAAoB,EAAE,SAAS,wBAAwB,EAMnE,CAAC;AAEF,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,EACnD,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,SAAS,CAAC,EAAE,GAAG,SAAS,EAChC,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,IAAI,EAAE,SAAS,CAAC,EAAE,GACjB,GAAG,CAAC,CAAC,CAAC,CAER"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const SIMPLE_STATUS_FIELDS = [
|
|
2
|
+
'status',
|
|
3
|
+
'publish_date',
|
|
4
|
+
];
|
|
5
|
+
export const FULL_STATUS_FIELDS = [
|
|
6
|
+
'type',
|
|
7
|
+
'state',
|
|
8
|
+
'status',
|
|
9
|
+
'publish_date',
|
|
10
|
+
];
|
|
11
|
+
export const SIMPLE_METADATA_FIELDS = [
|
|
12
|
+
'author',
|
|
13
|
+
'description',
|
|
14
|
+
'tags',
|
|
15
|
+
];
|
|
16
|
+
export const FULL_METADATA_FIELDS = [
|
|
17
|
+
'author',
|
|
18
|
+
'description',
|
|
19
|
+
'tags',
|
|
20
|
+
'url',
|
|
21
|
+
'fileKey',
|
|
22
|
+
];
|
|
23
|
+
/** The fields to render: an explicit allow-list wins over the mode. */
|
|
24
|
+
export function resolveContentFields(mode, fields, simple, full) {
|
|
25
|
+
return new Set(fields ?? (mode === 'simple' ? simple : full));
|
|
26
|
+
}
|
|
@@ -9,4 +9,18 @@ export declare function createContentEditorImageRecord(apiBaseUrl: string, input
|
|
|
9
9
|
mimeType: string;
|
|
10
10
|
}): Promise<ContentEditorAsset | null>;
|
|
11
11
|
export declare function resolveContentEditorImageSelection(apiBaseUrl: string, selected: ImageLike | File | string): Promise<ContentEditorAsset | null>;
|
|
12
|
+
/** Natural pixel size of an image, as used to choose a thumbnail placement. */
|
|
13
|
+
export interface ContentEditorImageDimensions {
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The size of an attached image: from the asset's own `width`/`height` (or
|
|
19
|
+
* `metadata.width`/`metadata.height`) when recorded, otherwise by loading
|
|
20
|
+
* `src` in the browser. Resolves `null` when neither is available (no DOM,
|
|
21
|
+
* load error, or `timeoutMs` elapsed).
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveContentEditorImageDimensions(asset: Record<string, unknown> | null | undefined, src: string, options?: {
|
|
24
|
+
timeoutMs?: number;
|
|
25
|
+
}): Promise<ContentEditorImageDimensions | null>;
|
|
12
26
|
//# sourceMappingURL=content-editor-media.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-editor-media.d.ts","sourceRoot":"","sources":["../../src/svelte/content-editor-media.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAEnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClD,MAAM,CAUR;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAO1E;AAED,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmBzE;AAWD,wBAAsB,8BAA8B,CAClD,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE;IACL,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,GACA,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAgBpC;AAED,wBAAsB,kCAAkC,CACtD,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,GAClC,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA6BpC"}
|
|
1
|
+
{"version":3,"file":"content-editor-media.d.ts","sourceRoot":"","sources":["../../src/svelte/content-editor-media.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAEnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClD,MAAM,CAUR;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAO1E;AAED,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmBzE;AAWD,wBAAsB,8BAA8B,CAClD,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE;IACL,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,GACA,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAgBpC;AAED,wBAAsB,kCAAkC,CACtD,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,GAClC,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA6BpC;AAED,+EAA+E;AAC/E,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAOD;;;;;GAKG;AACH,wBAAsB,mCAAmC,CACvD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EACjD,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,OAAO,CAAC,4BAA4B,GAAG,IAAI,CAAC,CAmC9C"}
|
|
@@ -82,3 +82,44 @@ export async function resolveContentEditorImageSelection(apiBaseUrl, selected) {
|
|
|
82
82
|
}
|
|
83
83
|
return null;
|
|
84
84
|
}
|
|
85
|
+
function positiveDimension(value) {
|
|
86
|
+
const number = Number(value);
|
|
87
|
+
return Number.isFinite(number) && number > 0 ? number : null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The size of an attached image: from the asset's own `width`/`height` (or
|
|
91
|
+
* `metadata.width`/`metadata.height`) when recorded, otherwise by loading
|
|
92
|
+
* `src` in the browser. Resolves `null` when neither is available (no DOM,
|
|
93
|
+
* load error, or `timeoutMs` elapsed).
|
|
94
|
+
*/
|
|
95
|
+
export async function resolveContentEditorImageDimensions(asset, src, options = {}) {
|
|
96
|
+
const metadata = asset?.metadata && typeof asset.metadata === 'object'
|
|
97
|
+
? asset.metadata
|
|
98
|
+
: {};
|
|
99
|
+
const width = positiveDimension(asset?.width ?? metadata.width);
|
|
100
|
+
const height = positiveDimension(asset?.height ?? metadata.height);
|
|
101
|
+
if (width && height) {
|
|
102
|
+
return { width, height };
|
|
103
|
+
}
|
|
104
|
+
const ImageConstructor = globalThis.Image;
|
|
105
|
+
if (!src || typeof ImageConstructor !== 'function') {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return new Promise((resolve) => {
|
|
109
|
+
const image = new ImageConstructor();
|
|
110
|
+
const timer = setTimeout(() => resolve(null), options.timeoutMs ?? 8000);
|
|
111
|
+
image.onload = () => {
|
|
112
|
+
clearTimeout(timer);
|
|
113
|
+
const naturalWidth = positiveDimension(image.naturalWidth);
|
|
114
|
+
const naturalHeight = positiveDimension(image.naturalHeight);
|
|
115
|
+
resolve(naturalWidth && naturalHeight
|
|
116
|
+
? { width: naturalWidth, height: naturalHeight }
|
|
117
|
+
: null);
|
|
118
|
+
};
|
|
119
|
+
image.onerror = () => {
|
|
120
|
+
clearTimeout(timer);
|
|
121
|
+
resolve(null);
|
|
122
|
+
};
|
|
123
|
+
image.src = src;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ImageLike } from '@happyvertical/smrt-images/svelte';
|
|
2
|
+
import { type ContentMainPicture } from '../body-format.js';
|
|
2
3
|
import { type ContentEditorAsset, type ContentEditorFormData, type ContentEditorInitialContent } from './content-editor-form.js';
|
|
3
4
|
export interface CreateContentEditorStateOptions {
|
|
4
5
|
content?: ContentEditorInitialContent | null;
|
|
@@ -9,6 +10,7 @@ export declare class ContentEditorState {
|
|
|
9
10
|
private _fieldUndoStack;
|
|
10
11
|
private _lastAppliedFields;
|
|
11
12
|
private _showUndoBanner;
|
|
13
|
+
private _bodyImageSignature;
|
|
12
14
|
constructor(options?: CreateContentEditorStateOptions);
|
|
13
15
|
get form(): ContentEditorFormData;
|
|
14
16
|
get snapshot(): {
|
|
@@ -30,6 +32,21 @@ export declare class ContentEditorState {
|
|
|
30
32
|
addAsset(asset: ContentEditorAsset | ImageLike | Record<string, unknown>): void;
|
|
31
33
|
removeAsset(assetId: string): void;
|
|
32
34
|
setThumbnailAsset(assetId: string | null): void;
|
|
35
|
+
/**
|
|
36
|
+
* The main picture (thumbnail) as the story decides it: the picture the
|
|
37
|
+
* person chose, else the first picture in the story (see
|
|
38
|
+
* `resolveBodyMainPicture`).
|
|
39
|
+
*/
|
|
40
|
+
get mainPicture(): ContentMainPicture;
|
|
41
|
+
/**
|
|
42
|
+
* Apply the main-picture rule after the story changed: the first picture
|
|
43
|
+
* in the story becomes the thumbnail unless one was chosen. Runs only
|
|
44
|
+
* when the story's pictures (or the choice) changed since the last call
|
|
45
|
+
* or `reset`, so editing text never replaces a thumbnail that was set
|
|
46
|
+
* some other way. A story without pictures keeps the current thumbnail.
|
|
47
|
+
* Returns true when the thumbnail changed.
|
|
48
|
+
*/
|
|
49
|
+
syncMainPictureFromBody(): boolean;
|
|
33
50
|
}
|
|
34
51
|
export declare function createContentEditorState(options?: CreateContentEditorStateOptions): ContentEditorState;
|
|
35
52
|
//# sourceMappingURL=content-editor-state.svelte.d.ts.map
|