wiki-formant 0.87.0 → 0.88.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/README.md +2 -2
- package/dist/base.css +9 -1
- package/dist/block-editor.d.ts +6 -1
- package/dist/block-editor.js +5 -0
- package/dist/blocks.d.ts +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -883,7 +883,7 @@ const SCHEMA: BlockSchema<Block> = {
|
|
|
883
883
|
<BlockEditor blocks={blocks} onChange={setBlocks} schema={SCHEMA} kit={KIT} />
|
|
884
884
|
```
|
|
885
885
|
|
|
886
|
-
The dispatch stays a `switch` over the wiki's own union, so a new type is a compile error there. `CodeTabsFields`, `StatsFields`, `EventsFields`, `ReferencesFields`, `LinkGridFields`, `BannerFields`, `PageListFields`, `ListFields`, `ColumnsFields` and `InfoboxFields` take the core blocks `wiki-formant/blocks` declares; the two containers hold the same list, offering `nestedTypes`. `Field`, `Choice` and `LimitField` are exported for a wiki's own editors, so its native types wear the same kit. A card is marked `data-selected` while it is being edited and `data-nested` inside a container; a type the build does not know is shown by its raw type and carried through untouched. Keep the kit and the schema stable — a module constant or a `useMemo` — since both reach every card through context, and a fresh one re-renders every card on every keystroke.
|
|
886
|
+
The dispatch stays a `switch` over the wiki's own union, so a new type is a compile error there. `CodeTabsFields`, `StatsFields`, `TestimonialFields`, `EventsFields`, `ReferencesFields`, `LinkGridFields`, `BannerFields`, `PageListFields`, `ListFields`, `ColumnsFields` and `InfoboxFields` take the core blocks `wiki-formant/blocks` declares; the two containers hold the same list, offering `nestedTypes`. `Field`, `Choice` and `LimitField` are exported for a wiki's own editors, so its native types wear the same kit. A card is marked `data-selected` while it is being edited and `data-nested` inside a container; a type the build does not know is shown by its raw type and carried through untouched. Keep the kit and the schema stable — a module constant or a `useMemo` — since both reach every card through context, and a fresh one re-renders every card on every keystroke.
|
|
887
887
|
|
|
888
888
|
An editor that draws each block in place, with a list of its own (miow's), hosts the same fields in `<BlockFieldsKit kit={KIT}>`, without `<BlockEditor>`. Only the two container fields need the full editor, since they hold a block list.
|
|
889
889
|
|
|
@@ -893,7 +893,7 @@ An `events` block is `{ upcoming?, past?, items: [{ id, date, end?, text }] }`:
|
|
|
893
893
|
|
|
894
894
|
A banner with no text of its own shows `BANNER_MESSAGES` from `wiki-formant/text`, a sentence per variant that names no wiki; `BannerView` takes it unless `message` overrides it.
|
|
895
895
|
|
|
896
|
-
The core blocks are `ContentBlock`, `CodeTabsBlock`, `StatsBlock`, `LinkGridBlock`, `ReferencesBlock`, `BannerBlock`, `TestimonialBlock`, `EventsBlock`, `ListBlock`, `ColumnsBlock<A>` and `InfoboxBlock<A>`, `A` being the wiki's atomic union. A wiki builds its union from
|
|
896
|
+
The core blocks are `ContentBlock`, `CodeTabsBlock`, `StatsBlock`, `LinkGridBlock`, `ReferencesBlock`, `BannerBlock`, `TestimonialBlock`, `EventsBlock`, `ListBlock`, `ColumnsBlock<A>` and `InfoboxBlock<A>`, `A` being the wiki's atomic union. `CoreLeafBlock` is every one of them but the list and the containers, as one union, and `CoreLeafType` its types. A wiki builds its atomic union from it, `CoreLeafBlock | ListBlock | its native types`, with its own `list` holding its own page rows, and derives its `BlockType` from the result. A leaf added here then reaches every wiki with the release, and fails to compile there until its label, its view and its fields are wired: a `Record` keyed by the block types is missing a key, and a switch closed with `block satisfies never` has a case left over. miow, whose union is zod's, asserts that it carries every `CoreLeafType`.
|
|
897
897
|
|
|
898
898
|
`ListBlock` is one list of the wiki's pages where those two were two: the pages in a section (`source: 'under'`), the newest, in a section or across the wiki (`'newest'`, `count`), or pages picked by hand (`'chosen'`, `pages`, keyed as the wiki keys a page, an id or a path), shown as links with their age or as cards (`show`). A wiki resolves it to `items` as it does a page list. `ListFields` edits it, with `pages` to pick from and `sections` to name; a wiki with a source of its own, a shop's products say, passes it in `sources` and draws its fields as `children`.
|
|
899
899
|
|
package/dist/base.css
CHANGED
|
@@ -155,7 +155,8 @@ html[data-sidebar='closed'] .wiki-sidebar { width: 0; }
|
|
|
155
155
|
The structure three or four sites had each restated around this markup;
|
|
156
156
|
padding, gaps, radii and colour stay theirs. A stats block is two columns,
|
|
157
157
|
three or four from 40rem; a code-tab strip is a row of buttons; a banner sets
|
|
158
|
-
its icon beside its text; a long address in an infobox wraps;
|
|
158
|
+
its icon beside its text; a long address in an infobox wraps; a testimonial
|
|
159
|
+
sets its photo, round, beside who said it; an events
|
|
159
160
|
block sets every row's dates in one column, shared by Upcoming and Past
|
|
160
161
|
through a subgrid, and stacks them over the words wherever it is narrower
|
|
161
162
|
than 30rem: a phone, or a narrow column. */
|
|
@@ -174,6 +175,9 @@ html[data-sidebar='closed'] .wiki-sidebar { width: 0; }
|
|
|
174
175
|
sits outside the article's prose box, and on radix.wiki ran 709px. */
|
|
175
176
|
.link-grid-group-description { max-width: var(--measure); }
|
|
176
177
|
.infobox-series { display: flex; flex-direction: column; }
|
|
178
|
+
.testimonial figcaption { display: flex; align-items: center; gap: 0.75rem; }
|
|
179
|
+
.testimonial figcaption img { width: 2.5rem; height: 2.5rem; border-radius: 50%; object-fit: cover; }
|
|
180
|
+
.testimonial figcaption > span { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 0.5rem; }
|
|
177
181
|
.events { display: grid; grid-template-columns: auto 1fr; container-type: inline-size; }
|
|
178
182
|
.events > *, .event-list li { grid-column: 1 / -1; }
|
|
179
183
|
.event-list, .event-list li { display: grid; grid-template-columns: subgrid; }
|
|
@@ -308,6 +312,10 @@ html[data-sidebar='closed'] .wiki-sidebar { width: 0; }
|
|
|
308
312
|
|
|
309
313
|
.facet-summary { margin: 0; font-size: var(--ui-small); color: var(--ui-muted); }
|
|
310
314
|
|
|
315
|
+
.testimonial { margin: 1.5rem 0; }
|
|
316
|
+
.testimonial > blockquote { margin: 0 0 0.75rem; font-size: 1.125rem; }
|
|
317
|
+
.testimonial figcaption small { color: var(--ui-muted); }
|
|
318
|
+
|
|
311
319
|
.events { column-gap: 1rem; margin-block: 1rem; }
|
|
312
320
|
.events h2 { margin: 0 0 1rem; }
|
|
313
321
|
.events ol ~ h2 { margin-top: 2.5rem; }
|
package/dist/block-editor.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ComponentType, type ReactElement, type ReactNode } from 'react';
|
|
2
|
-
import { type BannerBlock, type CodeTabsBlock, type ColumnsBlock, type EventsBlock, type InfoboxBlock, type LinkGridBlock, type ReferencesBlock, type StatsBlock } from './blocks.js';
|
|
2
|
+
import { type BannerBlock, type CodeTabsBlock, type ColumnsBlock, type EventsBlock, type InfoboxBlock, type LinkGridBlock, type ReferencesBlock, type StatsBlock, type TestimonialBlock } from './blocks.js';
|
|
3
3
|
export interface BlockEditorClassNames {
|
|
4
4
|
/** A page's block list. */
|
|
5
5
|
list?: string;
|
|
@@ -167,6 +167,11 @@ export declare function StatsFields({ block, onUpdate, hint }: {
|
|
|
167
167
|
onUpdate: (block: StatsBlock) => void;
|
|
168
168
|
hint?: string;
|
|
169
169
|
}): import("react").JSX.Element;
|
|
170
|
+
/** Someone's words exactly, and who they are: their name, and optionally their role and photo. */
|
|
171
|
+
export declare function TestimonialFields({ block, onUpdate }: {
|
|
172
|
+
block: TestimonialBlock;
|
|
173
|
+
onUpdate: (block: TestimonialBlock) => void;
|
|
174
|
+
}): import("react").JSX.Element;
|
|
170
175
|
/**
|
|
171
176
|
* Events in the order they were written, each with how its dates read and
|
|
172
177
|
* where the page sets it today: the page sorts them itself, and moves each on
|
package/dist/block-editor.js
CHANGED
|
@@ -163,6 +163,11 @@ export function StatsFields({ block, onUpdate, hint }) {
|
|
|
163
163
|
const set = (next) => onUpdate({ ...block, items: next });
|
|
164
164
|
return (_jsxs("div", { className: c.stack, children: [_jsx(Choice, { label: "Per row", value: String(block.columns), options: ['2', '3', '4'].map(n => ({ value: n, label: n })), onChange: n => onUpdate({ ...block, columns: Number(n) }) }), items.map((item, i) => (_jsxs("div", { className: c.row, children: [_jsx(TextInput, { label: "Figure", className: c.figure, value: item.value, onChange: value => set(replaceAt(items, i, { ...item, value: value ?? '' })) }), _jsx(TextInput, { label: "What it counts", value: item.label, onChange: label => set(replaceAt(items, i, { ...item, label: label ?? '' })) }), _jsx(Remove, { label: `Remove figure ${i + 1}`, onPress: () => set(removeAt(items, i)) })] }, item.id))), _jsx(Add, { onPress: () => set([...items, { id: newId(), value: '', label: '' }]), children: "Add figure" }), hint && _jsx("small", { className: c.muted, children: hint })] }));
|
|
165
165
|
}
|
|
166
|
+
/** Someone's words exactly, and who they are: their name, and optionally their role and photo. */
|
|
167
|
+
export function TestimonialFields({ block, onUpdate }) {
|
|
168
|
+
const c = useEditorContext().kit.classNames;
|
|
169
|
+
return (_jsxs("div", { className: c.stack, children: [_jsx(Field, { label: "Their words", children: _jsx("textarea", { "aria-label": "Their words", placeholder: "Their words, exactly as they said them", rows: 3, className: c.input, value: block.quote, onChange: e => onUpdate({ ...block, quote: e.target.value }) }) }), _jsxs("div", { className: c.row, children: [_jsx(TextInput, { label: "Who said them", value: block.author, onChange: author => onUpdate({ ...block, author: author ?? '' }) }), _jsx(TextInput, { label: "Their role (optional)", optional: true, value: block.role, onChange: role => onUpdate({ ...block, role }) })] }), _jsx(TextInput, { label: "Photo address (optional)", type: "url", placeholder: "https://", optional: true, value: block.avatarUrl, onChange: avatarUrl => onUpdate({ ...block, avatarUrl }) })] }));
|
|
170
|
+
}
|
|
166
171
|
/**
|
|
167
172
|
* Events in the order they were written, each with how its dates read and
|
|
168
173
|
* where the page sets it today: the page sorts them itself, and moves each on
|
package/dist/blocks.d.ts
CHANGED
|
@@ -139,6 +139,16 @@ export interface BannerBlock {
|
|
|
139
139
|
variant: BannerVariant;
|
|
140
140
|
text?: string;
|
|
141
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* The leaves every wiki here stores alike, as one union: a repo builds its own
|
|
144
|
+
* atomic union from it, `CoreLeafBlock | ListBlock | its native types`, so a
|
|
145
|
+
* leaf added here reaches every repo with the release, and every record keyed
|
|
146
|
+
* by its block types and every exhaustive switch over them fails to compile
|
|
147
|
+
* there until it is drawn, edited and labelled. The list is left out because
|
|
148
|
+
* each repo resolves its `items` to its own rows.
|
|
149
|
+
*/
|
|
150
|
+
export type CoreLeafBlock = ContentBlock | CodeTabsBlock | StatsBlock | LinkGridBlock | ReferencesBlock | BannerBlock | TestimonialBlock | EventsBlock;
|
|
151
|
+
export type CoreLeafType = CoreLeafBlock['type'];
|
|
142
152
|
/** `A` is the wiki's atomic union: a container never holds another container. */
|
|
143
153
|
export interface ColumnsBlock<A> {
|
|
144
154
|
id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wiki-formant",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.88.0",
|
|
4
4
|
"description": "The portable half of a wiki: derived taxonomy and facet controls, a version-negotiating MCP transport, markdown twins, block rendering, a rich-text editor engine, conditional-GET plumbing, and the headers and CSP every origin sends.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|