@estiva-app/ui 0.66.0 → 0.68.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/dist/BlockNodes.d.ts +12 -1
- package/dist/BlockNodes.d.ts.map +1 -1
- package/dist/EditorTableControls.d.ts +38 -0
- package/dist/EditorTableControls.d.ts.map +1 -0
- package/dist/LinkChips.d.ts +82 -0
- package/dist/LinkChips.d.ts.map +1 -0
- package/dist/NavItem.d.ts +11 -1
- package/dist/NavItem.d.ts.map +1 -1
- package/dist/ReferenceCards.d.ts +77 -0
- package/dist/ReferenceCards.d.ts.map +1 -0
- package/dist/ReferenceMenu.d.ts +18 -0
- package/dist/ReferenceMenu.d.ts.map +1 -0
- package/dist/RichText.d.ts +9 -2
- package/dist/RichText.d.ts.map +1 -1
- package/dist/SelectionToolbar.d.ts +9 -1
- package/dist/SelectionToolbar.d.ts.map +1 -1
- package/dist/editor.d.ts +4 -0
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +750 -27
- package/dist/editor.js.map +4 -4
- package/dist/index.js +62 -33
- package/dist/index.js.map +4 -4
- package/package.json +2 -1
- package/registry.json +414 -4
- package/src/BlockNodes.test.tsx +2 -1
- package/src/BlockNodes.tsx +51 -9
- package/src/EditorTableControls.mdx +78 -0
- package/src/EditorTableControls.stories.tsx +63 -0
- package/src/EditorTableControls.test.tsx +288 -0
- package/src/EditorTableControls.tsx +255 -0
- package/src/LinkChips.mdx +57 -0
- package/src/LinkChips.stories.tsx +67 -0
- package/src/LinkChips.test.tsx +178 -0
- package/src/LinkChips.ts +243 -0
- package/src/NavItem.mdx +10 -0
- package/src/NavItem.stories.tsx +23 -1
- package/src/NavItem.test.tsx +36 -0
- package/src/NavItem.tsx +40 -16
- package/src/ReferenceCards.mdx +79 -0
- package/src/ReferenceCards.stories.tsx +64 -0
- package/src/ReferenceCards.test.tsx +143 -0
- package/src/ReferenceCards.ts +225 -0
- package/src/ReferenceMenu.mdx +75 -0
- package/src/ReferenceMenu.stories.tsx +59 -0
- package/src/ReferenceMenu.test.tsx +289 -0
- package/src/ReferenceMenu.tsx +346 -0
- package/src/RichText.test.tsx +17 -0
- package/src/RichText.tsx +36 -4
- package/src/SelectionToolbar.tsx +10 -2
- package/src/editor.ts +14 -0
- package/src/pages.test.ts +3 -0
- package/src/registry/registry.test.ts +7 -7
- package/src/registry/siblings.test.ts +2 -2
- package/stories/Choosing.mdx +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@estiva-app/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.68.0",
|
|
4
4
|
"description": "Estiva's design tokens (the contract) and a small set of primitives (a convenience) for every Estiva app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -136,6 +136,7 @@
|
|
|
136
136
|
"@tiptap/core": "^3.31.3",
|
|
137
137
|
"@tiptap/extension-code-block-lowlight": "^3.31.3",
|
|
138
138
|
"@tiptap/extension-mention": "^3.31.3",
|
|
139
|
+
"@tiptap/extension-table": "^3.31.3",
|
|
139
140
|
"@tiptap/pm": "^3.31.3",
|
|
140
141
|
"@tiptap/react": "^3.31.3",
|
|
141
142
|
"@tiptap/starter-kit": "^3.31.3",
|
package/registry.json
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
"kind": "package",
|
|
5
5
|
"repo": "estiva-ui",
|
|
6
6
|
"package": "@estiva-app/ui",
|
|
7
|
-
"packageVersion": "0.
|
|
8
|
-
"exports":
|
|
9
|
-
"typeExports":
|
|
7
|
+
"packageVersion": "0.68.0",
|
|
8
|
+
"exports": 162,
|
|
9
|
+
"typeExports": 152,
|
|
10
10
|
"files": null
|
|
11
11
|
},
|
|
12
12
|
"storybook": {
|
|
@@ -15,6 +15,44 @@
|
|
|
15
15
|
"devUrl": "http://localhost:6008"
|
|
16
16
|
},
|
|
17
17
|
"entries": [
|
|
18
|
+
{
|
|
19
|
+
"name": "appendTableColumn",
|
|
20
|
+
"repo": "estiva-ui",
|
|
21
|
+
"kind": "helper",
|
|
22
|
+
"importPath": "@estiva-app/ui/editor",
|
|
23
|
+
"sourceFile": "src/EditorTableControls.tsx",
|
|
24
|
+
"purpose": "A column after the last one: the ➕ right of the table.",
|
|
25
|
+
"purposeFrom": "comment",
|
|
26
|
+
"props": [],
|
|
27
|
+
"variants": [],
|
|
28
|
+
"ownsBehaviours": [],
|
|
29
|
+
"status": "stable",
|
|
30
|
+
"migrationStage": null,
|
|
31
|
+
"docsId": "primitives-editortablecontrols--docs",
|
|
32
|
+
"storyId": "primitives-editortablecontrols--default",
|
|
33
|
+
"docPage": null,
|
|
34
|
+
"app": null,
|
|
35
|
+
"looks": []
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "appendTableRow",
|
|
39
|
+
"repo": "estiva-ui",
|
|
40
|
+
"kind": "helper",
|
|
41
|
+
"importPath": "@estiva-app/ui/editor",
|
|
42
|
+
"sourceFile": "src/EditorTableControls.tsx",
|
|
43
|
+
"purpose": "A row after the last one: the ➕ under the table.",
|
|
44
|
+
"purposeFrom": "comment",
|
|
45
|
+
"props": [],
|
|
46
|
+
"variants": [],
|
|
47
|
+
"ownsBehaviours": [],
|
|
48
|
+
"status": "stable",
|
|
49
|
+
"migrationStage": null,
|
|
50
|
+
"docsId": "primitives-editortablecontrols--docs",
|
|
51
|
+
"storyId": "primitives-editortablecontrols--default",
|
|
52
|
+
"docPage": null,
|
|
53
|
+
"app": null,
|
|
54
|
+
"looks": []
|
|
55
|
+
},
|
|
18
56
|
{
|
|
19
57
|
"name": "applyFormat",
|
|
20
58
|
"repo": "estiva-ui",
|
|
@@ -1963,6 +2001,44 @@
|
|
|
1963
2001
|
"app": null,
|
|
1964
2002
|
"looks": []
|
|
1965
2003
|
},
|
|
2004
|
+
{
|
|
2005
|
+
"name": "deleteTableColumn",
|
|
2006
|
+
"repo": "estiva-ui",
|
|
2007
|
+
"kind": "helper",
|
|
2008
|
+
"importPath": "@estiva-app/ui/editor",
|
|
2009
|
+
"sourceFile": "src/EditorTableControls.tsx",
|
|
2010
|
+
"purpose": "The same for a column: the last one deletes the table.",
|
|
2011
|
+
"purposeFrom": "comment",
|
|
2012
|
+
"props": [],
|
|
2013
|
+
"variants": [],
|
|
2014
|
+
"ownsBehaviours": [],
|
|
2015
|
+
"status": "stable",
|
|
2016
|
+
"migrationStage": null,
|
|
2017
|
+
"docsId": "primitives-editortablecontrols--docs",
|
|
2018
|
+
"storyId": "primitives-editortablecontrols--default",
|
|
2019
|
+
"docPage": null,
|
|
2020
|
+
"app": null,
|
|
2021
|
+
"looks": []
|
|
2022
|
+
},
|
|
2023
|
+
{
|
|
2024
|
+
"name": "deleteTableRow",
|
|
2025
|
+
"repo": "estiva-ui",
|
|
2026
|
+
"kind": "helper",
|
|
2027
|
+
"importPath": "@estiva-app/ui/editor",
|
|
2028
|
+
"sourceFile": "src/EditorTableControls.tsx",
|
|
2029
|
+
"purpose": "The cell's row, or the whole table when it is its only one: a table holds at least one row (prosemirror-tables refuses to delete it).",
|
|
2030
|
+
"purposeFrom": "comment",
|
|
2031
|
+
"props": [],
|
|
2032
|
+
"variants": [],
|
|
2033
|
+
"ownsBehaviours": [],
|
|
2034
|
+
"status": "stable",
|
|
2035
|
+
"migrationStage": null,
|
|
2036
|
+
"docsId": "primitives-editortablecontrols--docs",
|
|
2037
|
+
"storyId": "primitives-editortablecontrols--default",
|
|
2038
|
+
"docPage": null,
|
|
2039
|
+
"app": null,
|
|
2040
|
+
"looks": []
|
|
2041
|
+
},
|
|
1966
2042
|
{
|
|
1967
2043
|
"name": "DialogShell",
|
|
1968
2044
|
"repo": "estiva-ui",
|
|
@@ -2292,6 +2368,47 @@
|
|
|
2292
2368
|
"app": null,
|
|
2293
2369
|
"looks": []
|
|
2294
2370
|
},
|
|
2371
|
+
{
|
|
2372
|
+
"name": "EditorTableControls",
|
|
2373
|
+
"repo": "estiva-ui",
|
|
2374
|
+
"kind": "component",
|
|
2375
|
+
"importPath": "@estiva-app/ui/editor",
|
|
2376
|
+
"sourceFile": "src/EditorTableControls.tsx",
|
|
2377
|
+
"purpose": "A table's own controls in a Tiptap editor: point at a cell for a handle on its row and on its column, and a ➕ bar under the table and right of it.",
|
|
2378
|
+
"purposeFrom": "page",
|
|
2379
|
+
"props": [
|
|
2380
|
+
{
|
|
2381
|
+
"name": "editor",
|
|
2382
|
+
"takes": "Editor | null",
|
|
2383
|
+
"required": true,
|
|
2384
|
+
"note": "The editor, with TableKit (`@tiptap/extension-table`) in its extensions."
|
|
2385
|
+
},
|
|
2386
|
+
{
|
|
2387
|
+
"name": "children",
|
|
2388
|
+
"takes": "anything",
|
|
2389
|
+
"required": true,
|
|
2390
|
+
"note": "The `EditorContent`."
|
|
2391
|
+
},
|
|
2392
|
+
{
|
|
2393
|
+
"name": "className",
|
|
2394
|
+
"takes": "text",
|
|
2395
|
+
"required": false,
|
|
2396
|
+
"note": null
|
|
2397
|
+
}
|
|
2398
|
+
],
|
|
2399
|
+
"variants": [],
|
|
2400
|
+
"ownsBehaviours": [],
|
|
2401
|
+
"status": "stable",
|
|
2402
|
+
"migrationStage": null,
|
|
2403
|
+
"docsId": "primitives-editortablecontrols--docs",
|
|
2404
|
+
"storyId": "primitives-editortablecontrols--default",
|
|
2405
|
+
"docPage": "src/EditorTableControls.mdx",
|
|
2406
|
+
"app": null,
|
|
2407
|
+
"looks": [
|
|
2408
|
+
"rounded-lg border border-border-default bg-bg-elevated shadow-lg shadow-none -translate-x-1/2 -translate-y-1/2",
|
|
2409
|
+
"rounded-lg border border-border-default bg-bg-elevated shadow-lg shadow-none"
|
|
2410
|
+
]
|
|
2411
|
+
},
|
|
2295
2412
|
{
|
|
2296
2413
|
"name": "EmptyState",
|
|
2297
2414
|
"repo": "estiva-ui",
|
|
@@ -2612,6 +2729,25 @@
|
|
|
2612
2729
|
"app": null,
|
|
2613
2730
|
"looks": []
|
|
2614
2731
|
},
|
|
2732
|
+
{
|
|
2733
|
+
"name": "findLinkChips",
|
|
2734
|
+
"repo": "estiva-ui",
|
|
2735
|
+
"kind": "helper",
|
|
2736
|
+
"importPath": "@estiva-app/ui/editor",
|
|
2737
|
+
"sourceFile": "src/LinkChips.ts",
|
|
2738
|
+
"purpose": "What to change in a document, and what to ask.",
|
|
2739
|
+
"purposeFrom": "comment",
|
|
2740
|
+
"props": [],
|
|
2741
|
+
"variants": [],
|
|
2742
|
+
"ownsBehaviours": [],
|
|
2743
|
+
"status": "stable",
|
|
2744
|
+
"migrationStage": null,
|
|
2745
|
+
"docsId": "primitives-linkchips--docs",
|
|
2746
|
+
"storyId": "primitives-linkchips--in-an-editor",
|
|
2747
|
+
"docPage": null,
|
|
2748
|
+
"app": null,
|
|
2749
|
+
"looks": []
|
|
2750
|
+
},
|
|
2615
2751
|
{
|
|
2616
2752
|
"name": "Form",
|
|
2617
2753
|
"repo": "estiva-ui",
|
|
@@ -3220,6 +3356,25 @@
|
|
|
3220
3356
|
"app": null,
|
|
3221
3357
|
"looks": []
|
|
3222
3358
|
},
|
|
3359
|
+
{
|
|
3360
|
+
"name": "isReferenceMenuOpen",
|
|
3361
|
+
"repo": "estiva-ui",
|
|
3362
|
+
"kind": "helper",
|
|
3363
|
+
"importPath": "@estiva-app/ui/editor",
|
|
3364
|
+
"sourceFile": "src/ReferenceMenu.tsx",
|
|
3365
|
+
"purpose": "Whether the menu is open, for an editor's own Escape: while it is, Escape closes it rather than leaving.",
|
|
3366
|
+
"purposeFrom": "comment",
|
|
3367
|
+
"props": [],
|
|
3368
|
+
"variants": [],
|
|
3369
|
+
"ownsBehaviours": [],
|
|
3370
|
+
"status": "stable",
|
|
3371
|
+
"migrationStage": null,
|
|
3372
|
+
"docsId": "primitives-referencemenu--docs",
|
|
3373
|
+
"storyId": "primitives-referencemenu--in-an-editor",
|
|
3374
|
+
"docPage": null,
|
|
3375
|
+
"app": null,
|
|
3376
|
+
"looks": []
|
|
3377
|
+
},
|
|
3223
3378
|
{
|
|
3224
3379
|
"name": "isSuggestionActive",
|
|
3225
3380
|
"repo": "estiva-ui",
|
|
@@ -3550,6 +3705,25 @@
|
|
|
3550
3705
|
"underline underline-offset-2 hover:text-text-primary truncate after:rounded-md focus-visible:outline-none"
|
|
3551
3706
|
]
|
|
3552
3707
|
},
|
|
3708
|
+
{
|
|
3709
|
+
"name": "LinkChips",
|
|
3710
|
+
"repo": "estiva-ui",
|
|
3711
|
+
"kind": "component",
|
|
3712
|
+
"importPath": "@estiva-app/ui/editor",
|
|
3713
|
+
"sourceFile": "src/LinkChips.ts",
|
|
3714
|
+
"purpose": "A URL in a document that the app recognises reads as a chip of what it points at, and stays that URL when the document is saved.",
|
|
3715
|
+
"purposeFrom": "page",
|
|
3716
|
+
"props": [],
|
|
3717
|
+
"variants": [],
|
|
3718
|
+
"ownsBehaviours": [],
|
|
3719
|
+
"status": "stable",
|
|
3720
|
+
"migrationStage": null,
|
|
3721
|
+
"docsId": "primitives-linkchips--docs",
|
|
3722
|
+
"storyId": "primitives-linkchips--in-an-editor",
|
|
3723
|
+
"docPage": "src/LinkChips.mdx",
|
|
3724
|
+
"app": null,
|
|
3725
|
+
"looks": []
|
|
3726
|
+
},
|
|
3553
3727
|
{
|
|
3554
3728
|
"name": "ListColumn",
|
|
3555
3729
|
"repo": "estiva-ui",
|
|
@@ -4240,6 +4414,12 @@
|
|
|
4240
4414
|
"required": false,
|
|
4241
4415
|
"note": "The ⋮'s accessible name and tooltip. Default \"More options for {label}\"."
|
|
4242
4416
|
},
|
|
4417
|
+
{
|
|
4418
|
+
"name": "action",
|
|
4419
|
+
"takes": "SectionAction",
|
|
4420
|
+
"required": false,
|
|
4421
|
+
"note": "One button beside the ⋮, shown with it: any 16px icon, its tooltip and its handler — a `SectionHeader` action's shape."
|
|
4422
|
+
},
|
|
4243
4423
|
{
|
|
4244
4424
|
"name": "hint",
|
|
4245
4425
|
"takes": "anything",
|
|
@@ -5362,6 +5542,63 @@
|
|
|
5362
5542
|
"app": null,
|
|
5363
5543
|
"looks": []
|
|
5364
5544
|
},
|
|
5545
|
+
{
|
|
5546
|
+
"name": "referenceAtSelection",
|
|
5547
|
+
"repo": "estiva-ui",
|
|
5548
|
+
"kind": "helper",
|
|
5549
|
+
"importPath": "@estiva-app/ui/editor",
|
|
5550
|
+
"sourceFile": "src/ReferenceCards.ts",
|
|
5551
|
+
"purpose": "The chip the person has selected, with what it names and its card — or null.",
|
|
5552
|
+
"purposeFrom": "comment",
|
|
5553
|
+
"props": [],
|
|
5554
|
+
"variants": [],
|
|
5555
|
+
"ownsBehaviours": [],
|
|
5556
|
+
"status": "stable",
|
|
5557
|
+
"migrationStage": null,
|
|
5558
|
+
"docsId": "primitives-referencecards--docs",
|
|
5559
|
+
"storyId": "primitives-referencecards--in-an-editor",
|
|
5560
|
+
"docPage": null,
|
|
5561
|
+
"app": null,
|
|
5562
|
+
"looks": []
|
|
5563
|
+
},
|
|
5564
|
+
{
|
|
5565
|
+
"name": "referenceCardPlacements",
|
|
5566
|
+
"repo": "estiva-ui",
|
|
5567
|
+
"kind": "helper",
|
|
5568
|
+
"importPath": "@estiva-app/ui/editor",
|
|
5569
|
+
"sourceFile": "src/ReferenceCards.ts",
|
|
5570
|
+
"purpose": "Every line that asks for a card, in document order.",
|
|
5571
|
+
"purposeFrom": "comment",
|
|
5572
|
+
"props": [],
|
|
5573
|
+
"variants": [],
|
|
5574
|
+
"ownsBehaviours": [],
|
|
5575
|
+
"status": "stable",
|
|
5576
|
+
"migrationStage": null,
|
|
5577
|
+
"docsId": "primitives-referencecards--docs",
|
|
5578
|
+
"storyId": "primitives-referencecards--in-an-editor",
|
|
5579
|
+
"docPage": null,
|
|
5580
|
+
"app": null,
|
|
5581
|
+
"looks": []
|
|
5582
|
+
},
|
|
5583
|
+
{
|
|
5584
|
+
"name": "ReferenceCards",
|
|
5585
|
+
"repo": "estiva-ui",
|
|
5586
|
+
"kind": "component",
|
|
5587
|
+
"importPath": "@estiva-app/ui/editor",
|
|
5588
|
+
"sourceFile": "src/ReferenceCards.ts",
|
|
5589
|
+
"purpose": "A chip in a document can ask for a card after its line: compact, detailed or none.",
|
|
5590
|
+
"purposeFrom": "page",
|
|
5591
|
+
"props": [],
|
|
5592
|
+
"variants": [],
|
|
5593
|
+
"ownsBehaviours": [],
|
|
5594
|
+
"status": "stable",
|
|
5595
|
+
"migrationStage": null,
|
|
5596
|
+
"docsId": "primitives-referencecards--docs",
|
|
5597
|
+
"storyId": "primitives-referencecards--in-an-editor",
|
|
5598
|
+
"docPage": "src/ReferenceCards.mdx",
|
|
5599
|
+
"app": null,
|
|
5600
|
+
"looks": []
|
|
5601
|
+
},
|
|
5365
5602
|
{
|
|
5366
5603
|
"name": "referenceMenu",
|
|
5367
5604
|
"repo": "estiva-ui",
|
|
@@ -5406,6 +5643,91 @@
|
|
|
5406
5643
|
"app": null,
|
|
5407
5644
|
"looks": []
|
|
5408
5645
|
},
|
|
5646
|
+
{
|
|
5647
|
+
"name": "ReferenceMenu",
|
|
5648
|
+
"repo": "estiva-ui",
|
|
5649
|
+
"kind": "component",
|
|
5650
|
+
"importPath": "@estiva-app/ui/editor",
|
|
5651
|
+
"sourceFile": "src/ReferenceMenu.tsx",
|
|
5652
|
+
"purpose": "What a chip in a document offers whoever is writing it: Open, and its Card — none, compact or detailed.",
|
|
5653
|
+
"purposeFrom": "page",
|
|
5654
|
+
"props": [],
|
|
5655
|
+
"variants": [],
|
|
5656
|
+
"ownsBehaviours": [],
|
|
5657
|
+
"status": "stable",
|
|
5658
|
+
"migrationStage": null,
|
|
5659
|
+
"docsId": "primitives-referencemenu--docs",
|
|
5660
|
+
"storyId": "primitives-referencemenu--in-an-editor",
|
|
5661
|
+
"docPage": "src/ReferenceMenu.mdx",
|
|
5662
|
+
"app": null,
|
|
5663
|
+
"looks": []
|
|
5664
|
+
},
|
|
5665
|
+
{
|
|
5666
|
+
"name": "referenceMenuClick",
|
|
5667
|
+
"repo": "estiva-ui",
|
|
5668
|
+
"kind": "helper",
|
|
5669
|
+
"importPath": "@estiva-app/ui/editor",
|
|
5670
|
+
"sourceFile": "src/ReferenceMenu.tsx",
|
|
5671
|
+
"purpose": "A click on the chip at `pos`, from its node view: while editing, with the menu installed, it opens the menu, and the caller stops the click there.",
|
|
5672
|
+
"purposeFrom": "comment",
|
|
5673
|
+
"props": [],
|
|
5674
|
+
"variants": [],
|
|
5675
|
+
"ownsBehaviours": [],
|
|
5676
|
+
"status": "stable",
|
|
5677
|
+
"migrationStage": null,
|
|
5678
|
+
"docsId": "primitives-referencemenu--docs",
|
|
5679
|
+
"storyId": "primitives-referencemenu--in-an-editor",
|
|
5680
|
+
"docPage": null,
|
|
5681
|
+
"app": null,
|
|
5682
|
+
"looks": []
|
|
5683
|
+
},
|
|
5684
|
+
{
|
|
5685
|
+
"name": "ReferenceMenuView",
|
|
5686
|
+
"repo": "estiva-ui",
|
|
5687
|
+
"kind": "component",
|
|
5688
|
+
"importPath": "@estiva-app/ui/editor",
|
|
5689
|
+
"sourceFile": "src/ReferenceMenu.tsx",
|
|
5690
|
+
"purpose": "The menu `ReferenceMenu` holds, hung under its chip.",
|
|
5691
|
+
"purposeFrom": "comment",
|
|
5692
|
+
"props": [
|
|
5693
|
+
{
|
|
5694
|
+
"name": "editor",
|
|
5695
|
+
"takes": "Editor | null",
|
|
5696
|
+
"required": true,
|
|
5697
|
+
"note": null
|
|
5698
|
+
}
|
|
5699
|
+
],
|
|
5700
|
+
"variants": [],
|
|
5701
|
+
"ownsBehaviours": [
|
|
5702
|
+
{
|
|
5703
|
+
"id": "portal",
|
|
5704
|
+
"behaviour": "Floats on top of the page"
|
|
5705
|
+
},
|
|
5706
|
+
{
|
|
5707
|
+
"id": "press-outside",
|
|
5708
|
+
"behaviour": "Closes on a press outside"
|
|
5709
|
+
},
|
|
5710
|
+
{
|
|
5711
|
+
"id": "page-keys",
|
|
5712
|
+
"behaviour": "Takes its keys by itself"
|
|
5713
|
+
},
|
|
5714
|
+
{
|
|
5715
|
+
"id": "focus",
|
|
5716
|
+
"behaviour": "Holds focus inside while open, and gives it back"
|
|
5717
|
+
},
|
|
5718
|
+
{
|
|
5719
|
+
"id": "follow",
|
|
5720
|
+
"behaviour": "Stays attached to its anchor on scroll and resize"
|
|
5721
|
+
}
|
|
5722
|
+
],
|
|
5723
|
+
"status": "stable",
|
|
5724
|
+
"migrationStage": null,
|
|
5725
|
+
"docsId": "primitives-referencemenu--docs",
|
|
5726
|
+
"storyId": "primitives-referencemenu--in-an-editor",
|
|
5727
|
+
"docPage": null,
|
|
5728
|
+
"app": null,
|
|
5729
|
+
"looks": []
|
|
5730
|
+
},
|
|
5409
5731
|
{
|
|
5410
5732
|
"name": "ReferenceNode",
|
|
5411
5733
|
"repo": "estiva-ui",
|
|
@@ -5444,6 +5766,25 @@
|
|
|
5444
5766
|
"app": null,
|
|
5445
5767
|
"looks": []
|
|
5446
5768
|
},
|
|
5769
|
+
{
|
|
5770
|
+
"name": "refreshLinkChips",
|
|
5771
|
+
"repo": "estiva-ui",
|
|
5772
|
+
"kind": "helper",
|
|
5773
|
+
"importPath": "@estiva-app/ui/editor",
|
|
5774
|
+
"sourceFile": "src/LinkChips.ts",
|
|
5775
|
+
"purpose": "Look at the document again — after the app learned what more URLs name some other way.",
|
|
5776
|
+
"purposeFrom": "comment",
|
|
5777
|
+
"props": [],
|
|
5778
|
+
"variants": [],
|
|
5779
|
+
"ownsBehaviours": [],
|
|
5780
|
+
"status": "stable",
|
|
5781
|
+
"migrationStage": null,
|
|
5782
|
+
"docsId": "primitives-linkchips--docs",
|
|
5783
|
+
"storyId": "primitives-linkchips--in-an-editor",
|
|
5784
|
+
"docPage": null,
|
|
5785
|
+
"app": null,
|
|
5786
|
+
"looks": []
|
|
5787
|
+
},
|
|
5447
5788
|
{
|
|
5448
5789
|
"name": "RichText",
|
|
5449
5790
|
"repo": "estiva-ui",
|
|
@@ -5483,6 +5824,12 @@
|
|
|
5483
5824
|
"required": false,
|
|
5484
5825
|
"note": "Draws a block this part has no design for (an attachment, a widget)."
|
|
5485
5826
|
},
|
|
5827
|
+
{
|
|
5828
|
+
"name": "renderAfter",
|
|
5829
|
+
"takes": "a handler",
|
|
5830
|
+
"required": false,
|
|
5831
|
+
"note": "Draws something after a line of text: after a paragraph, a heading or a quote, and inside a list item or a table cell after its words — where a document's chip asks for its card (SPEC §13.3)."
|
|
5832
|
+
},
|
|
5486
5833
|
{
|
|
5487
5834
|
"name": "onTick",
|
|
5488
5835
|
"takes": "a handler",
|
|
@@ -5512,7 +5859,7 @@
|
|
|
5512
5859
|
"[&_:not(pre)>code]:rounded-sm [&_:not(pre)>code]:bg-bg-code [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:border [&_:not(pre)>code]:border-border-default [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-text-primary",
|
|
5513
5860
|
"[&_pre>code]:text-[1em] [&_pre]:whitespace-pre-wrap [&_pre]:break-words [&_pre]:rounded-md [&_pre]:bg-bg-code [&_pre]:px-3 [&_pre]:py-2.5 [&_pre]:font-mono [&_pre]:text-[0.85em] [&_pre]:leading-relaxed [&_pre]:text-text-primary",
|
|
5514
5861
|
"[&_:is(.hljs-keyword,.hljs-doctag,.hljs-type,.hljs-template-tag,.hljs-template-variable)]:text-syntax-keyword [&_.hljs-title]:text-syntax-function [&_:is(.hljs-number,.hljs-literal,.hljs-attr,.hljs-attribute,.hljs-meta,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id)]:text-syntax-constant [&_:is(.hljs-string,.hljs-regexp)]:text-syntax-string [&_:is(.hljs-built_in,.hljs-symbol)]:text-syntax-variable [&_.hljs-comment]:text-syntax-comment [&_:is(.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo)]:text-syntax-tag",
|
|
5515
|
-
"[&_:is(th,td)>p]:m-0 [&_:is(th,td)]:border [&_:is(th,td)]:border-border-default [&_:is(th,td)]:px-2 [&_:is(th,td)]:py-1 [&_:is(th,td)]:text-left [&_:is(th,td)]:align-top [&_table]:w-full [&_table]:border-collapse [&_th]:bg-bg-code [&_th]:font-medium [&_th]:text-text-primary",
|
|
5862
|
+
"[&_:is(th,td)>p]:m-0 [&_:is(th,td)]:border [&_:is(th,td)]:border-border-default [&_:is(th,td)]:px-2 [&_:is(th,td)]:py-1 [&_:is(th,td)]:text-left [&_:is(th,td)]:align-top [&_table]:my-2 [&_table]:w-full [&_table]:border-collapse [&_th]:bg-bg-code [&_th]:font-medium [&_th]:text-text-primary",
|
|
5516
5863
|
"[&_em]:italic [&_strong]:font-semibold [&_strong]:text-text-primary [&_u]:underline [&_u]:decoration-text-muted [&_u]:underline-offset-2",
|
|
5517
5864
|
"text-body-2 leading-normal [&>:is(h2,h3)]:text-body-2 [&>:is(h2,h3)]:font-semibold [&>h1]:text-h4",
|
|
5518
5865
|
"text-caption leading-snug [&>:is(h1,h2,h3)]:mb-0.5 [&>:is(h1,h2,h3)]:mt-1.5 [&>:is(h1,h2,h3)+:is(h1,h2,h3)]:mt-1 [&>:is(h1,h2,h3):last-child]:mb-0 [&>:is(h2,h3)]:text-caption [&>:is(h2,h3)]:font-semibold [&>h1]:text-body-2 [&>h1]:font-semibold"
|
|
@@ -6031,6 +6378,12 @@
|
|
|
6031
6378
|
"takes": "true/false",
|
|
6032
6379
|
"required": false,
|
|
6033
6380
|
"note": "The Link button and its address field. Needs a link mark in the editor and `KeptSelection`."
|
|
6381
|
+
},
|
|
6382
|
+
{
|
|
6383
|
+
"name": "children",
|
|
6384
|
+
"takes": "anything",
|
|
6385
|
+
"required": false,
|
|
6386
|
+
"note": "More of the strip, after the marks: the app's own `ToolbarButton`s for what is selected — a chip's card, say."
|
|
6034
6387
|
}
|
|
6035
6388
|
],
|
|
6036
6389
|
"variants": [],
|
|
@@ -6064,6 +6417,44 @@
|
|
|
6064
6417
|
"app": null,
|
|
6065
6418
|
"looks": []
|
|
6066
6419
|
},
|
|
6420
|
+
{
|
|
6421
|
+
"name": "setReferenceCard",
|
|
6422
|
+
"repo": "estiva-ui",
|
|
6423
|
+
"kind": "helper",
|
|
6424
|
+
"importPath": "@estiva-app/ui/editor",
|
|
6425
|
+
"sourceFile": "src/ReferenceCards.ts",
|
|
6426
|
+
"purpose": "Sets the card of the selected chip. `none` removes it.",
|
|
6427
|
+
"purposeFrom": "comment",
|
|
6428
|
+
"props": [],
|
|
6429
|
+
"variants": [],
|
|
6430
|
+
"ownsBehaviours": [],
|
|
6431
|
+
"status": "stable",
|
|
6432
|
+
"migrationStage": null,
|
|
6433
|
+
"docsId": "primitives-referencecards--docs",
|
|
6434
|
+
"storyId": "primitives-referencecards--in-an-editor",
|
|
6435
|
+
"docPage": null,
|
|
6436
|
+
"app": null,
|
|
6437
|
+
"looks": []
|
|
6438
|
+
},
|
|
6439
|
+
{
|
|
6440
|
+
"name": "setReferenceCardAt",
|
|
6441
|
+
"repo": "estiva-ui",
|
|
6442
|
+
"kind": "helper",
|
|
6443
|
+
"importPath": "@estiva-app/ui/editor",
|
|
6444
|
+
"sourceFile": "src/ReferenceCards.ts",
|
|
6445
|
+
"purpose": "Sets the card of the chip at `pos` — one that names something.",
|
|
6446
|
+
"purposeFrom": "comment",
|
|
6447
|
+
"props": [],
|
|
6448
|
+
"variants": [],
|
|
6449
|
+
"ownsBehaviours": [],
|
|
6450
|
+
"status": "stable",
|
|
6451
|
+
"migrationStage": null,
|
|
6452
|
+
"docsId": "primitives-referencecards--docs",
|
|
6453
|
+
"storyId": "primitives-referencecards--in-an-editor",
|
|
6454
|
+
"docPage": null,
|
|
6455
|
+
"app": null,
|
|
6456
|
+
"looks": []
|
|
6457
|
+
},
|
|
6067
6458
|
{
|
|
6068
6459
|
"name": "shortcutLabel",
|
|
6069
6460
|
"repo": "estiva-ui",
|
|
@@ -7485,6 +7876,25 @@
|
|
|
7485
7876
|
"app": null,
|
|
7486
7877
|
"looks": []
|
|
7487
7878
|
},
|
|
7879
|
+
{
|
|
7880
|
+
"name": "useReferenceCards",
|
|
7881
|
+
"repo": "estiva-ui",
|
|
7882
|
+
"kind": "hook",
|
|
7883
|
+
"importPath": "@estiva-app/ui/editor",
|
|
7884
|
+
"sourceFile": "src/ReferenceCards.ts",
|
|
7885
|
+
"purpose": "The slots to draw cards into, kept current as the document changes.",
|
|
7886
|
+
"purposeFrom": "comment",
|
|
7887
|
+
"props": [],
|
|
7888
|
+
"variants": [],
|
|
7889
|
+
"ownsBehaviours": [],
|
|
7890
|
+
"status": "stable",
|
|
7891
|
+
"migrationStage": null,
|
|
7892
|
+
"docsId": "primitives-referencecards--docs",
|
|
7893
|
+
"storyId": "primitives-referencecards--in-an-editor",
|
|
7894
|
+
"docPage": null,
|
|
7895
|
+
"app": null,
|
|
7896
|
+
"looks": []
|
|
7897
|
+
},
|
|
7488
7898
|
{
|
|
7489
7899
|
"name": "useToast",
|
|
7490
7900
|
"repo": "estiva-ui",
|
package/src/BlockNodes.test.tsx
CHANGED
|
@@ -79,7 +79,8 @@ describe('what the editor hands back', () => {
|
|
|
79
79
|
it('keeps a reference an atom, with its uri and the marks it carries', () => {
|
|
80
80
|
editor = new Editor({ extensions: EXTENSIONS, content: DOCUMENT })
|
|
81
81
|
const reference = (editor.getJSON() as Json).content?.[1].content?.[1]
|
|
82
|
-
|
|
82
|
+
// No card chosen, no key a later version added (SPEC §13.3), and not a URL chip.
|
|
83
|
+
expect(reference).toEqual({ type: 'reference', attrs: { uri: 'nostr:naddr1example', marks: ['bold'], embed: null, extra: null, href: null } })
|
|
83
84
|
})
|
|
84
85
|
|
|
85
86
|
it('keeps every imeta field on a file, which ProseMirror drops when undeclared', () => {
|
package/src/BlockNodes.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComponentType } from 'react'
|
|
1
|
+
import type { ComponentType, MouseEvent } from 'react'
|
|
2
2
|
import { Extension, InputRule, Node, type Editor } from '@tiptap/core'
|
|
3
3
|
import { DOMSerializer, type Node as ProseMirrorNode, type Slice } from '@tiptap/pm/model'
|
|
4
4
|
import { Plugin, PluginKey, type EditorState, type Transaction } from '@tiptap/pm/state'
|
|
@@ -7,6 +7,7 @@ import type { EditorView, NodeView } from '@tiptap/pm/view'
|
|
|
7
7
|
import { NodeViewWrapper, ReactNodeViewRenderer, ReactRenderer, type ReactNodeViewProps } from '@tiptap/react'
|
|
8
8
|
import { Checkbox, type CheckboxProps } from './Checkbox'
|
|
9
9
|
import { calloutLook } from './RichText'
|
|
10
|
+
import { referenceMenuClick } from './ReferenceMenu'
|
|
10
11
|
|
|
11
12
|
/*
|
|
12
13
|
* The four nodes an editor of a block document needs that a stock schema does
|
|
@@ -364,9 +365,13 @@ export const BlockId = Extension.create({
|
|
|
364
365
|
},
|
|
365
366
|
})
|
|
366
367
|
|
|
367
|
-
/**
|
|
368
|
+
/** An http(s) URL, or null. */
|
|
369
|
+
const webUrl = (raw: string | null): string | null => (raw && /^https?:\/\/\S+$/i.test(raw) ? raw : null)
|
|
370
|
+
|
|
371
|
+
/** What a reference's view is handed: the `nostr:` URI it stands for, and the URL a URL chip was written as. */
|
|
368
372
|
export interface ReferenceViewProps {
|
|
369
373
|
uri: string
|
|
374
|
+
href?: string
|
|
370
375
|
}
|
|
371
376
|
|
|
372
377
|
export interface ReferenceNodeOptions {
|
|
@@ -384,6 +389,16 @@ export interface ReferenceNodeOptions {
|
|
|
384
389
|
* nobody edits half a `naddr`. Selecting it selects the whole reference, which
|
|
385
390
|
* is also how deleting one works. `marks` carries the run's other marks, so a
|
|
386
391
|
* bold reference comes back bold.
|
|
392
|
+
*
|
|
393
|
+
* `embed` is the card its writer chose to draw after its block — `compact`,
|
|
394
|
+
* `detailed`, or null for none (SPEC §13.3, "A reference's card") — and `extra`
|
|
395
|
+
* every key of the mark this version does not know. Both are declared so that
|
|
396
|
+
* ProseMirror keeps them: an undeclared attribute is dropped when the node is
|
|
397
|
+
* made, and the card with it. `ReferenceCards` draws the cards.
|
|
398
|
+
*
|
|
399
|
+
* `href` makes it a **URL chip**: an app URL that reads as the chip of what it
|
|
400
|
+
* names, and is that URL on the wire (§13.3). `uri` is what it names, filled in
|
|
401
|
+
* by `LinkChips` once the app has resolved it; until then it draws as the URL.
|
|
387
402
|
*/
|
|
388
403
|
export const ReferenceNode = Node.create<ReferenceNodeOptions>({
|
|
389
404
|
name: 'reference',
|
|
@@ -397,8 +412,14 @@ export const ReferenceNode = Node.create<ReferenceNodeOptions>({
|
|
|
397
412
|
},
|
|
398
413
|
addAttributes() {
|
|
399
414
|
return {
|
|
400
|
-
|
|
415
|
+
// A pasted URL chip keeps only its URL: what it names is the editor's to resolve (`LinkChips`), never
|
|
416
|
+
// the clipboard's, which could show one object while saving another URL (security review).
|
|
417
|
+
uri: { default: '', parseHTML: (element: HTMLElement) => (webUrl(element.getAttribute('data-href')) ? '' : (element.getAttribute('data-reference') ?? '')) },
|
|
401
418
|
marks: { default: [] as string[] },
|
|
419
|
+
embed: { default: null as string | null, parseHTML: (element: HTMLElement) => element.getAttribute('data-embed') },
|
|
420
|
+
extra: { default: null as Record<string, unknown> | null, parseHTML: () => null },
|
|
421
|
+
// An http(s) URL only: `LinkChips` makes no other, and a pasted `javascript:` must not reach a saved link.
|
|
422
|
+
href: { default: null as string | null, parseHTML: (element: HTMLElement) => webUrl(element.getAttribute('data-href')) },
|
|
402
423
|
}
|
|
403
424
|
},
|
|
404
425
|
parseHTML() {
|
|
@@ -406,16 +427,37 @@ export const ReferenceNode = Node.create<ReferenceNodeOptions>({
|
|
|
406
427
|
},
|
|
407
428
|
renderHTML({ node }) {
|
|
408
429
|
// A copy to the clipboard as HTML, and the whole drawing when no view is given.
|
|
409
|
-
|
|
430
|
+
// The card goes along, so a paste keeps it; a URL chip copies as its URL.
|
|
431
|
+
const embed = typeof node.attrs.embed === 'string' ? { 'data-embed': node.attrs.embed } : {}
|
|
432
|
+
const href = typeof node.attrs.href === 'string' && node.attrs.href ? { 'data-href': node.attrs.href } : {}
|
|
433
|
+
return ['span', { 'data-reference': String(node.attrs.uri), ...embed, ...href }, String(node.attrs.href || node.attrs.uri)]
|
|
434
|
+
},
|
|
435
|
+
renderText({ node }) {
|
|
436
|
+
return String(node.attrs.href || node.attrs.uri)
|
|
410
437
|
},
|
|
411
438
|
addNodeView() {
|
|
412
439
|
const View = this.options.view
|
|
413
440
|
if (!View) return null
|
|
414
|
-
return ReactNodeViewRenderer(({ node }: ReactNodeViewProps) =>
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
441
|
+
return ReactNodeViewRenderer(({ node, editor, getPos }: ReactNodeViewProps) => {
|
|
442
|
+
const uri = String(node.attrs.uri ?? '')
|
|
443
|
+
const href = typeof node.attrs.href === 'string' && node.attrs.href ? node.attrs.href : undefined
|
|
444
|
+
return (
|
|
445
|
+
<NodeViewWrapper
|
|
446
|
+
as="span"
|
|
447
|
+
className="inline"
|
|
448
|
+
// While editing, a click opens the chip's menu (`ReferenceMenu`) rather than following the chip.
|
|
449
|
+
onClickCapture={(event: MouseEvent) => {
|
|
450
|
+
const pos = getPos()
|
|
451
|
+
if (typeof pos !== 'number' || !referenceMenuClick(editor, pos)) return
|
|
452
|
+
event.preventDefault()
|
|
453
|
+
event.stopPropagation()
|
|
454
|
+
}}
|
|
455
|
+
>
|
|
456
|
+
{/* A URL chip not resolved yet reads as the URL it was written as. */}
|
|
457
|
+
{uri ? <View uri={uri} {...(href ? { href } : {})} /> : <span>{href}</span>}
|
|
458
|
+
</NodeViewWrapper>
|
|
459
|
+
)
|
|
460
|
+
})
|
|
419
461
|
},
|
|
420
462
|
})
|
|
421
463
|
|