@charcuterie/ui 3.4.0 → 3.5.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 +8 -0
- package/dist/markdownEditorCodeMirror/livePreview.d.ts.map +1 -1
- package/dist/markdownEditorCodeMirror/livePreview.js +346 -3
- package/dist/markdownEditorCodeMirror/livePreview.js.map +1 -1
- package/dist/markdownEditorCodeMirror/livePreviewRanges.d.ts +99 -1
- package/dist/markdownEditorCodeMirror/livePreviewRanges.d.ts.map +1 -1
- package/dist/markdownEditorCodeMirror/livePreviewRanges.js +370 -19
- package/dist/markdownEditorCodeMirror/livePreviewRanges.js.map +1 -1
- package/package.json +1 -1
- package/src/Accordion/Accordion.stories.tsx +1 -1
- package/src/AdaptiveGrid/AdaptiveGrid.stories.tsx +1 -1
- package/src/Alert/Alert.stories.tsx +1 -1
- package/src/Badge/Badge.stories.tsx +1 -1
- package/src/Board/Board.stories.tsx +1 -1
- package/src/Button/Button.stories.tsx +1 -1
- package/src/ButtonLink/ButtonLink.stories.tsx +1 -1
- package/src/Card/Card.stories.tsx +1 -1
- package/src/Checkbox/Checkbox.stories.tsx +1 -1
- package/src/ColorSchemeSwitcher/ColorSchemeSwitcher.stories.tsx +1 -1
- package/src/ColorSchemeToggle/ColorSchemeToggle.stories.tsx +1 -1
- package/src/Combobox/Combobox.stories.tsx +1 -1
- package/src/DataTable/DataTable.stories.tsx +1 -1
- package/src/DatePicker/DatePicker.stories.tsx +1 -1
- package/src/Dialog/Dialog.stories.tsx +1 -1
- package/src/EmptyState/EmptyState.stories.tsx +1 -1
- package/src/Field/Field.stories.tsx +1 -1
- package/src/FileDropZone/FileDropZone.stories.tsx +1 -1
- package/src/Header/Header.stories.tsx +1 -1
- package/src/IconButton/IconButton.stories.tsx +1 -1
- package/src/Lightbox/Lightbox.stories.tsx +1 -1
- package/src/Listbox/Listbox.stories.tsx +1 -1
- package/src/LiveStatusIndicator/LiveStatusIndicator.stories.tsx +1 -1
- package/src/LogViewer/LogViewer.stories.tsx +1 -1
- package/src/Main/Main.stories.tsx +1 -1
- package/src/MarkdownEditor/MarkdownEditor.stories.tsx +1 -1
- package/src/MediaTile/MediaTile.stories.tsx +1 -1
- package/src/Menu/Menu.stories.tsx +1 -1
- package/src/Modal/Modal.stories.tsx +1 -1
- package/src/Picker/Picker.stories.tsx +1 -1
- package/src/Popover/Popover.stories.tsx +1 -1
- package/src/ProgressBar/ProgressBar.stories.tsx +1 -1
- package/src/QueryBuilder/QueryBuilder.stories.tsx +1 -1
- package/src/RadioGroup/RadioGroup.stories.tsx +1 -1
- package/src/Rail/Rail.stories.tsx +1 -1
- package/src/SegmentedControl/SegmentedControl.stories.tsx +1 -1
- package/src/Select/Select.stories.tsx +17 -6
- package/src/Shell/Shell.stories.tsx +1 -1
- package/src/Skeleton/Skeleton.stories.tsx +1 -1
- package/src/SortableTableHeader/SortableTableHeader.stories.tsx +1 -1
- package/src/Spinner/Spinner.stories.tsx +1 -1
- package/src/Swatch/Swatch.stories.tsx +1 -1
- package/src/Switch/Switch.stories.tsx +1 -1
- package/src/Tabs/Tabs.stories.tsx +1 -1
- package/src/TextLink/TextLink.stories.tsx +1 -1
- package/src/Toast/Toast.stories.tsx +1 -1
- package/src/Toolbar/Toolbar.stories.tsx +1 -1
- package/src/Tooltip/Tooltip.stories.tsx +1 -1
- package/src/VisuallyHidden/VisuallyHidden.stories.tsx +1 -1
- package/src/markdownEditorCodeMirror/MarkdownEditorCodeMirror.mdx +28 -0
- package/src/markdownEditorCodeMirror/MarkdownEditorCodeMirror.stories.tsx +43 -1
- package/src/markdownEditorCodeMirror/livePreview.ts +465 -3
- package/src/markdownEditorCodeMirror/livePreviewRanges.test.ts +349 -8
- package/src/markdownEditorCodeMirror/livePreviewRanges.ts +669 -27
|
@@ -10,7 +10,7 @@ import { FileDropZone } from "./FileDropZone.tsx"
|
|
|
10
10
|
const noop = () => undefined
|
|
11
11
|
|
|
12
12
|
const meta = {
|
|
13
|
-
title: "Components/FileDropZone",
|
|
13
|
+
title: "Components/Controls/FileDropZone",
|
|
14
14
|
component: FileDropZone,
|
|
15
15
|
parameters: { layout: "padded" },
|
|
16
16
|
args: {
|
|
@@ -27,7 +27,7 @@ import { IconButton } from "./IconButton.tsx"
|
|
|
27
27
|
const UNDO_ICON = <UndoIcon />
|
|
28
28
|
|
|
29
29
|
const meta = {
|
|
30
|
-
title: "Components/IconButton",
|
|
30
|
+
title: "Components/Actions/IconButton",
|
|
31
31
|
component: IconButton,
|
|
32
32
|
parameters: { layout: "padded" },
|
|
33
33
|
argTypes: { size: controlSizeArgType },
|
|
@@ -24,7 +24,7 @@ const CONNECTION_STATUSES = [
|
|
|
24
24
|
] as const
|
|
25
25
|
|
|
26
26
|
const meta = {
|
|
27
|
-
title: "Components/LiveStatusIndicator",
|
|
27
|
+
title: "Components/Feedback/LiveStatusIndicator",
|
|
28
28
|
component: LiveStatusIndicator,
|
|
29
29
|
parameters: { layout: "padded" },
|
|
30
30
|
argTypes: { status: connectionStatusArgType },
|
|
@@ -25,7 +25,7 @@ const toPosterSrc = (label: string) =>
|
|
|
25
25
|
const MISSING_SRC = "/charcuterie-missing-poster.png"
|
|
26
26
|
|
|
27
27
|
const meta = {
|
|
28
|
-
title: "Components/MediaTile",
|
|
28
|
+
title: "Components/Data/MediaTile",
|
|
29
29
|
component: MediaTile,
|
|
30
30
|
parameters: { layout: "padded" },
|
|
31
31
|
args: { aspectRatio: "poster" },
|
|
@@ -24,7 +24,7 @@ const COLUMN_ITEMS: SegmentedItem[] = [
|
|
|
24
24
|
]
|
|
25
25
|
|
|
26
26
|
const meta = {
|
|
27
|
-
title: "Components/SegmentedControl",
|
|
27
|
+
title: "Components/Controls/SegmentedControl",
|
|
28
28
|
component: SegmentedControl,
|
|
29
29
|
parameters: { layout: "padded" },
|
|
30
30
|
argTypes: { size: controlSizeArgType },
|
|
@@ -41,13 +41,24 @@ const GROUPED: SelectItem[] = [
|
|
|
41
41
|
]
|
|
42
42
|
|
|
43
43
|
const meta = {
|
|
44
|
-
|
|
45
|
-
// moving it: the sidebar is the first place an agent looks for a
|
|
46
|
-
// picker, and a `Select` sitting between `Rail` and `Shell` reads
|
|
47
|
-
// as a component in good standing. Nothing new gets one — `Picker`
|
|
48
|
-
// is the drop-in. See the 2026-08-20 deprecation record.
|
|
49
|
-
title: "Deprecated/Select",
|
|
44
|
+
title: "Components/Controls/Select",
|
|
50
45
|
component: Select,
|
|
46
|
+
/**
|
|
47
|
+
* Deprecated — `Picker` is the drop-in. This is a **label, not a
|
|
48
|
+
* relocation**: the component still lives beside the other
|
|
49
|
+
* controls, where somebody looking for a picker will actually
|
|
50
|
+
* find it, and the sidebar paints a badge on it there. A
|
|
51
|
+
* `Deprecated/` section instead of a label hides the warning from
|
|
52
|
+
* everyone who does not already know to look for it, which is
|
|
53
|
+
* exactly backwards.
|
|
54
|
+
*
|
|
55
|
+
* Manager entries take the **intersection** of their children's
|
|
56
|
+
* tags, so tagging the meta puts the badge on the `Select` node
|
|
57
|
+
* itself, not just on each story underneath it.
|
|
58
|
+
* `sidebar.renderLabel` in `@charcuterie/storybook-config/manager`
|
|
59
|
+
* is what draws it.
|
|
60
|
+
*/
|
|
61
|
+
tags: ["deprecated"],
|
|
51
62
|
parameters: { layout: "padded" },
|
|
52
63
|
argTypes: { size: controlSizeArgType },
|
|
53
64
|
args: {
|
|
@@ -10,7 +10,7 @@ import { Card } from "../Card/Card.tsx"
|
|
|
10
10
|
import { Skeleton } from "./Skeleton.tsx"
|
|
11
11
|
|
|
12
12
|
const meta = {
|
|
13
|
-
title: "Components/Skeleton",
|
|
13
|
+
title: "Components/Feedback/Skeleton",
|
|
14
14
|
component: Skeleton,
|
|
15
15
|
parameters: { layout: "padded" },
|
|
16
16
|
args: { lineCount: 1, shape: "block" },
|
|
@@ -30,7 +30,7 @@ const CELL_CLASS =
|
|
|
30
30
|
* every table gets wrong the same way.
|
|
31
31
|
*/
|
|
32
32
|
const meta = {
|
|
33
|
-
title: "Components/SortableTableHeader",
|
|
33
|
+
title: "Components/Data/SortableTableHeader",
|
|
34
34
|
component: SortableTableHeader,
|
|
35
35
|
parameters: { layout: "padded" },
|
|
36
36
|
args: { onSort: noop },
|
|
@@ -20,7 +20,7 @@ const noop = () => undefined
|
|
|
20
20
|
* is the documented way to hold one for an action anyway.
|
|
21
21
|
*/
|
|
22
22
|
const meta = {
|
|
23
|
-
title: "Components/Toast",
|
|
23
|
+
title: "Components/Overlays/Toast",
|
|
24
24
|
component: Toast,
|
|
25
25
|
parameters: { layout: "padded" },
|
|
26
26
|
argTypes: { intent: intentArgType },
|
|
@@ -11,7 +11,7 @@ import { SettingsIcon } from "../icons.storyHelpers.tsx"
|
|
|
11
11
|
import { Tooltip } from "./Tooltip.tsx"
|
|
12
12
|
|
|
13
13
|
const meta = {
|
|
14
|
-
title: "Components/Tooltip",
|
|
14
|
+
title: "Components/Overlays/Tooltip",
|
|
15
15
|
component: Tooltip,
|
|
16
16
|
parameters: { layout: "centered" },
|
|
17
17
|
argTypes: { placement: placementArgType },
|
|
@@ -19,7 +19,7 @@ import { VisuallyHidden } from "./VisuallyHidden.tsx"
|
|
|
19
19
|
* loses translation.
|
|
20
20
|
*/
|
|
21
21
|
const meta = {
|
|
22
|
-
title: "
|
|
22
|
+
title: "Utilities/VisuallyHidden",
|
|
23
23
|
component: VisuallyHidden,
|
|
24
24
|
parameters: { layout: "padded" },
|
|
25
25
|
} satisfies Meta<typeof VisuallyHidden>
|
|
@@ -98,6 +98,34 @@ blank line at the top and bottom of the block that reads as a rendering bug. A l
|
|
|
98
98
|
stays, because hiding `-` turns an unordered list into indented prose — Obsidian substitutes
|
|
99
99
|
a `•`, which means choosing a width, and this component has no business choosing one.
|
|
100
100
|
|
|
101
|
+
## Tables render, and the caret edits them
|
|
102
|
+
|
|
103
|
+
<Canvas of={MarkdownEditorCodeMirrorStories.Tables} />
|
|
104
|
+
|
|
105
|
+
A table is the one construct on this surface whose meaning is *geometry*. Every other
|
|
106
|
+
decoration hangs on text CodeMirror draws anyway; a column cannot, because column two's text
|
|
107
|
+
is on four separate lines. So the pipes stop being drawn and a real `<table>` is drawn
|
|
108
|
+
instead — alignment from the delimiter row, and `**bold**`, `` `code` ``, links and images
|
|
109
|
+
rendering inside the cells exactly as they do in a paragraph.
|
|
110
|
+
|
|
111
|
+
**Click a cell and the markdown comes back with the caret in that cell.** That is the same
|
|
112
|
+
trade as a link or an image, and it is the only way in: you cannot edit a column you cannot
|
|
113
|
+
see. Arrow keys work too — Down from the line above enters at the top row, Up from below
|
|
114
|
+
enters at the bottom — because CodeMirror otherwise steps *over* a block widget and the
|
|
115
|
+
table would be unreachable without a mouse.
|
|
116
|
+
|
|
117
|
+
Three decisions worth knowing:
|
|
118
|
+
|
|
119
|
+
- **The widest row wins, not the header.** GFM drops cells past the header's width. An
|
|
120
|
+
editor that did the same would put text you typed on screen nowhere, so short rows gain
|
|
121
|
+
empty cells instead and nothing is ever hidden.
|
|
122
|
+
- **An empty cell keeps its column.** The parser emits no cell node for `| |`; the `|`
|
|
123
|
+
positions are what the columns are read from, so a blank cell does not shift the row.
|
|
124
|
+
- **A wide table scrolls inside its own block** rather than pushing the editor sideways.
|
|
125
|
+
|
|
126
|
+
`\|` — the only way to put a pipe *in* a cell — now conceals its backslash like any other
|
|
127
|
+
marker, in tables and everywhere else.
|
|
128
|
+
|
|
101
129
|
## Clicking a link opens it
|
|
102
130
|
|
|
103
131
|
Obsidian's behaviour, not VS Code's: where the markup is hidden, a link that looks like a
|
|
@@ -47,8 +47,30 @@ ip -br addr show
|
|
|
47
47
|
Replacement rails ordered from https://example.invalid/product?id=1234
|
|
48
48
|
`
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Alignment from the delimiter row, inline markup inside cells, a
|
|
52
|
+
* deliberately blank cell, and a row that is one column short —
|
|
53
|
+
* every table decision in one fixture.
|
|
54
|
+
*/
|
|
55
|
+
const TABLES = `## Rack inventory
|
|
56
|
+
|
|
57
|
+
| Port | Goes to | **Speed** | Notes |
|
|
58
|
+
| :--- | :---: | ---: | --- |
|
|
59
|
+
| 1 | uplink | 10G | swapped \`2026-08-19\` |
|
|
60
|
+
| 2 | | 1G | see [the runbook](https://example.invalid/runbook) |
|
|
61
|
+
| 3 | shelf | 1G |
|
|
62
|
+
| 4 | ~~spare~~ | — | pulled \\| relabel |
|
|
63
|
+
|
|
64
|
+
A table with no outer pipes is still a table:
|
|
65
|
+
|
|
66
|
+
Disk | Size
|
|
67
|
+
--- | ---:
|
|
68
|
+
front-left | 18 TB
|
|
69
|
+
front-right | 18 TB
|
|
70
|
+
`
|
|
71
|
+
|
|
50
72
|
const meta = {
|
|
51
|
-
title: "Components/MarkdownEditorCodeMirror",
|
|
73
|
+
title: "Components/Controls/MarkdownEditorCodeMirror",
|
|
52
74
|
component: MarkdownEditorCodeMirror,
|
|
53
75
|
parameters: { layout: "padded" },
|
|
54
76
|
args: {
|
|
@@ -145,3 +167,23 @@ export const CaretReveal: Story = {
|
|
|
145
167
|
label: "Description",
|
|
146
168
|
},
|
|
147
169
|
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* The construct whose meaning is geometry.
|
|
173
|
+
*
|
|
174
|
+
* Everything else on this surface is a decoration hung on text that
|
|
175
|
+
* is drawn anyway — a column is not, because column two's text is
|
|
176
|
+
* on four separate lines. So the pipes stop being drawn and a real
|
|
177
|
+
* table is drawn instead, alignment and all, with `**bold**` and
|
|
178
|
+
* links rendering inside the cells like anywhere else.
|
|
179
|
+
*
|
|
180
|
+
* Click a cell and the markdown comes back with the caret in that
|
|
181
|
+
* cell — the same trade the rest of the surface makes for a link or
|
|
182
|
+
* an image.
|
|
183
|
+
*/
|
|
184
|
+
export const Tables: Story = {
|
|
185
|
+
args: {
|
|
186
|
+
defaultValue: TABLES,
|
|
187
|
+
label: "Description",
|
|
188
|
+
},
|
|
189
|
+
}
|