@estiva-app/ui 0.64.0 → 0.65.1
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/CodeBlockColours.d.ts.map +1 -1
- package/dist/CollapsibleSection.d.ts +10 -1
- package/dist/CollapsibleSection.d.ts.map +1 -1
- package/dist/NavTree.d.ts +7 -1
- package/dist/NavTree.d.ts.map +1 -1
- package/dist/codeColours.d.ts +1 -12
- package/dist/codeColours.d.ts.map +1 -1
- package/dist/editor.js +11 -2
- package/dist/editor.js.map +2 -2
- package/dist/index.js +14 -9
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
- package/registry.json +14 -2
- package/src/CodeBlockColours.mdx +4 -3
- package/src/CodeBlockColours.test.ts +36 -0
- package/src/CodeBlockColours.ts +15 -1
- package/src/CollapsibleSection.mdx +7 -0
- package/src/CollapsibleSection.test.tsx +30 -0
- package/src/CollapsibleSection.tsx +15 -3
- package/src/NavTree.mdx +4 -1
- package/src/NavTree.test.tsx +10 -0
- package/src/NavTree.tsx +8 -1
- package/src/RichText.tsx +2 -2
- package/src/codeColours.ts +11 -3
- package/tailwind-preset.js +0 -1
- package/tokens.css +0 -10
package/package.json
CHANGED
package/registry.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"kind": "package",
|
|
5
5
|
"repo": "estiva-ui",
|
|
6
6
|
"package": "@estiva-app/ui",
|
|
7
|
-
"packageVersion": "0.
|
|
7
|
+
"packageVersion": "0.65.1",
|
|
8
8
|
"exports": 140,
|
|
9
9
|
"typeExports": 145,
|
|
10
10
|
"files": null
|
|
@@ -1248,6 +1248,12 @@
|
|
|
1248
1248
|
"required": false,
|
|
1249
1249
|
"note": null
|
|
1250
1250
|
},
|
|
1251
|
+
{
|
|
1252
|
+
"name": "pending",
|
|
1253
|
+
"takes": "true/false",
|
|
1254
|
+
"required": false,
|
|
1255
|
+
"note": "Opened, and its rows are not in yet: the title says open — the arrow turned, `aria-expanded`, `aria-busy` — and the panel stays shut until this is false, then slides open once, rows and all."
|
|
1256
|
+
},
|
|
1251
1257
|
{
|
|
1252
1258
|
"name": "storageKey",
|
|
1253
1259
|
"takes": "text",
|
|
@@ -4378,6 +4384,12 @@
|
|
|
4378
4384
|
"required": false,
|
|
4379
4385
|
"note": "Its rows are being read: a skeleton in their place."
|
|
4380
4386
|
},
|
|
4387
|
+
{
|
|
4388
|
+
"name": "pending",
|
|
4389
|
+
"takes": "true/false",
|
|
4390
|
+
"required": false,
|
|
4391
|
+
"note": "Opened, and its rows are being read: the arrow turns and the group stays shut until they are in, then opens once — `CollapsibleSection`'s."
|
|
4392
|
+
},
|
|
4381
4393
|
{
|
|
4382
4394
|
"name": "storageKey",
|
|
4383
4395
|
"takes": "text",
|
|
@@ -5415,7 +5427,7 @@
|
|
|
5415
5427
|
"looks": [
|
|
5416
5428
|
"[&_:is(ul,ol)]:pl-5 [&_li>p]:m-0 [&_li]:break-words [&_li]:marker:text-text-secondary [&_ol]:list-decimal [&_ul]:list-disc",
|
|
5417
5429
|
"[&_blockquote>p]:m-0 [&_blockquote]:border-l-[3px] [&_blockquote]:border-text-muted [&_blockquote]:pl-2.5",
|
|
5418
|
-
"[&_: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]:
|
|
5430
|
+
"[&_: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",
|
|
5419
5431
|
"[&_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",
|
|
5420
5432
|
"[&_: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",
|
|
5421
5433
|
"[&_: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",
|
package/src/CodeBlockColours.mdx
CHANGED
|
@@ -19,7 +19,7 @@ are the ones RichText reads it in, so writing looks the same as reading.
|
|
|
19
19
|
|
|
20
20
|
- Drawing text that is already written → **RichText**, which colours its code
|
|
21
21
|
blocks itself.
|
|
22
|
-
- Code in a sentence → the code mark. It
|
|
22
|
+
- Code in a sentence → the code mark. It takes no colours.
|
|
23
23
|
|
|
24
24
|
## How
|
|
25
25
|
|
|
@@ -38,8 +38,9 @@ useEditor({
|
|
|
38
38
|
class list; without it the words are named but drawn in one colour.
|
|
39
39
|
- The block keeps the name `codeBlock` and its `language`, so text written
|
|
40
40
|
before it was added reads the same.
|
|
41
|
-
- It colours highlight.js's 37 everyday languages
|
|
42
|
-
|
|
41
|
+
- It colours highlight.js's 37 everyday languages, only by the language the
|
|
42
|
+
block names (```` ```ts ```` then Enter). A block in any other language, or
|
|
43
|
+
in none, stays one colour: it never guesses, so it looks the same once read.
|
|
43
44
|
- The app installs `@tiptap/extension-code-block-lowlight`, as it installs the
|
|
44
45
|
other Tiptap parts.
|
|
45
46
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
/**
|
|
3
|
+
* CodeBlockColours colours a block only by the language it names, as RichText
|
|
4
|
+
* does when the text is read (Katerina, 9 October: never guess).
|
|
5
|
+
*/
|
|
6
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
7
|
+
import { Editor } from '@tiptap/core'
|
|
8
|
+
import StarterKit from '@tiptap/starter-kit'
|
|
9
|
+
import { CodeBlockColours } from './CodeBlockColours'
|
|
10
|
+
|
|
11
|
+
let editor: Editor | undefined
|
|
12
|
+
afterEach(() => editor?.destroy())
|
|
13
|
+
|
|
14
|
+
const coloured = (content: string) => {
|
|
15
|
+
editor = new Editor({ element: document.createElement('div'), extensions: [StarterKit.configure({ codeBlock: false }), CodeBlockColours], content })
|
|
16
|
+
return editor.view.dom.querySelectorAll('pre [class*="hljs-"]').length
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('CodeBlockColours', () => {
|
|
20
|
+
it('colours a block that names its language', () => {
|
|
21
|
+
expect(coloured('<pre><code class="language-ts">const done = items.length</code></pre>')).toBeGreaterThan(0)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('leaves a block that names no language in one colour, as RichText reads it', () => {
|
|
25
|
+
expect(coloured('<pre><code>const done = items.length</code></pre>')).toBe(0)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('leaves a block in a language it does not know in one colour', () => {
|
|
29
|
+
expect(coloured('<pre><code class="language-nothing">const done = items.length</code></pre>')).toBe(0)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('keeps the block a code block, with its language', () => {
|
|
33
|
+
coloured('<pre><code class="language-ts">const done = 1</code></pre>')
|
|
34
|
+
expect(editor!.getJSON().content?.[0]).toMatchObject({ type: 'codeBlock', attrs: { language: 'ts' } })
|
|
35
|
+
})
|
|
36
|
+
})
|
package/src/CodeBlockColours.ts
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
import { CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight'
|
|
3
3
|
import { lowlight } from './codeColours'
|
|
4
4
|
|
|
5
|
+
/*
|
|
6
|
+
The editor library guesses a language for a block that names none, or names
|
|
7
|
+
one it does not know, and colours it by the guess. RichText never guesses, so
|
|
8
|
+
that block was coloured while written and plain once read. A block is
|
|
9
|
+
coloured only by the language it names, while written and when read
|
|
10
|
+
(Katerina, 9 October: never guess).
|
|
11
|
+
*/
|
|
12
|
+
const namedOnly = {
|
|
13
|
+
highlight: (language: string, value: string) => lowlight().highlight(language, value),
|
|
14
|
+
highlightAuto: (value: string) => ({ type: 'root' as const, children: [{ type: 'text' as const, value }], data: { language: undefined, relevance: 0 } }),
|
|
15
|
+
listLanguages: () => lowlight().listLanguages(),
|
|
16
|
+
registered: (language: string) => lowlight().registered(language),
|
|
17
|
+
}
|
|
18
|
+
|
|
5
19
|
/**
|
|
6
20
|
* A code block in the editor, with the colours RichText reads it in (Katerina,
|
|
7
21
|
* 9 October): the same highlight.js languages, the same classes, and the
|
|
@@ -11,4 +25,4 @@ import { lowlight } from './codeColours'
|
|
|
11
25
|
* then add `CodeBlockColours`. The block keeps its name, `codeBlock`, and its
|
|
12
26
|
* `language` attribute, so nothing already written changes.
|
|
13
27
|
*/
|
|
14
|
-
export const CodeBlockColours = CodeBlockLowlight.configure({ lowlight })
|
|
28
|
+
export const CodeBlockColours = CodeBlockLowlight.configure({ lowlight: namedOnly })
|
|
@@ -20,6 +20,13 @@ toggle, and the rows under it, sliding shut and open.
|
|
|
20
20
|
reloads: this browser remembers, under that key. The app prefixes the
|
|
21
21
|
key (`app.sidebar.starred`).
|
|
22
22
|
- `open` + `onOpenChange` when the app owns the state.
|
|
23
|
+
- `pending` when the rows are read as it opens and usually arrive quickly:
|
|
24
|
+
the title turns open at once (and says `aria-busy`), the panel stays shut
|
|
25
|
+
until `pending` is false, then opens once with every row. A skeleton that
|
|
26
|
+
the rows replace would move everything below it twice. Only for rows not
|
|
27
|
+
yet drawn: on a section already showing its rows, `pending` shuts them
|
|
28
|
+
until it is false. The tests pin the state (open, busy, rows hidden); the
|
|
29
|
+
single slide is Chrome's to show, measured in Peek (OPT-11).
|
|
23
30
|
- `actions` for add, sort, filter beside the title — SectionHeader's,
|
|
24
31
|
revealed while the row is hovered or keyboard-focused.
|
|
25
32
|
- `look="row"` when the section is a row among rows — a folder in a
|
|
@@ -81,6 +81,36 @@ describe('CollapsibleSection', () => {
|
|
|
81
81
|
})
|
|
82
82
|
})
|
|
83
83
|
|
|
84
|
+
/** Opened before its rows are in (0.65.1, OPT-11): the title says open, the panel waits. */
|
|
85
|
+
describe('CollapsibleSection, pending', () => {
|
|
86
|
+
it('the title says open and busy while the rows stay shut, then they open', () => {
|
|
87
|
+
const { rerender } = render(<CollapsibleSection title="Section" open pending>{rows}</CollapsibleSection>)
|
|
88
|
+
expect(title().getAttribute('aria-expanded')).toBe('true')
|
|
89
|
+
expect(title().getAttribute('aria-busy')).toBe('true')
|
|
90
|
+
expect(screen.getByText('Item one').closest('[hidden]')).not.toBeNull()
|
|
91
|
+
rerender(<CollapsibleSection title="Section" open>{rows}</CollapsibleSection>)
|
|
92
|
+
expect(title().getAttribute('aria-expanded')).toBe('true')
|
|
93
|
+
expect(title().getAttribute('aria-busy')).toBeNull()
|
|
94
|
+
expect(screen.getByText('Item one').closest('[hidden]')).toBeNull()
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('a click while pending closes it', async () => {
|
|
98
|
+
const onOpenChange = vi.fn()
|
|
99
|
+
render(<CollapsibleSection title="Section" open pending onOpenChange={onOpenChange}>{rows}</CollapsibleSection>)
|
|
100
|
+
await userEvent.click(title())
|
|
101
|
+
expect(onOpenChange).toHaveBeenCalledWith(false)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('a closed section is not busy, and a click opens it', async () => {
|
|
105
|
+
const onOpenChange = vi.fn()
|
|
106
|
+
render(<CollapsibleSection title="Section" open={false} pending onOpenChange={onOpenChange}>{rows}</CollapsibleSection>)
|
|
107
|
+
expect(title().getAttribute('aria-expanded')).toBe('false')
|
|
108
|
+
expect(title().getAttribute('aria-busy')).toBeNull()
|
|
109
|
+
await userEvent.click(title())
|
|
110
|
+
expect(onOpenChange).toHaveBeenCalledWith(true)
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
|
|
84
114
|
/** What it hands its header (0.56.0): the folder's ⋮, the ⋮'s name, and the icon before the title. */
|
|
85
115
|
describe('CollapsibleSection, its header', () => {
|
|
86
116
|
it('passes menu and menuLabel on: the ⋮ is named by menuLabel and opens the menu', async () => {
|
|
@@ -30,6 +30,15 @@ export interface CollapsibleSectionProps {
|
|
|
30
30
|
/** The caller owns the state. */
|
|
31
31
|
open?: boolean
|
|
32
32
|
onOpenChange?: (open: boolean) => void
|
|
33
|
+
/**
|
|
34
|
+
* Opened, and its rows are not in yet: the title says open — the arrow
|
|
35
|
+
* turned, `aria-expanded`, `aria-busy` — and the panel stays shut until
|
|
36
|
+
* this is false, then slides open once, rows and all. A skeleton the rows
|
|
37
|
+
* then replace moves everything below twice (Peek's Folders, OPT-11). A
|
|
38
|
+
* click while pending closes it, as on an open section. Not for a re-read:
|
|
39
|
+
* on a section already showing its rows it shuts them until it is false.
|
|
40
|
+
*/
|
|
41
|
+
pending?: boolean
|
|
33
42
|
/** Remember open or closed in this browser, under this key. The app prefixes it. */
|
|
34
43
|
storageKey?: string
|
|
35
44
|
/** 16px, before the title; the arrow takes its place on hover — `SectionHeader`'s. */
|
|
@@ -85,7 +94,7 @@ function writeStored(key: string | undefined, open: boolean) {
|
|
|
85
94
|
}
|
|
86
95
|
}
|
|
87
96
|
|
|
88
|
-
export function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenChange, storageKey, icon, trailing, actions, menu, menuLabel, showActions, look = 'heading', indent = false, children, className, contentClassName }: CollapsibleSectionProps) {
|
|
97
|
+
export function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenChange, pending = false, storageKey, icon, trailing, actions, menu, menuLabel, showActions, look = 'heading', indent = false, children, className, contentClassName }: CollapsibleSectionProps) {
|
|
89
98
|
const [openState, setOpenState] = useState(() => readStored(storageKey) ?? defaultOpen)
|
|
90
99
|
const open = openProp ?? openState
|
|
91
100
|
const setOpen = (next: boolean) => {
|
|
@@ -93,9 +102,12 @@ export function CollapsibleSection({ title, defaultOpen = true, open: openProp,
|
|
|
93
102
|
writeStored(storageKey, next)
|
|
94
103
|
onOpenChange?.(next)
|
|
95
104
|
}
|
|
105
|
+
// Pending, Base UI holds the panel shut and so would open it on a click: the click is the title's, and the title says open.
|
|
106
|
+
// Only a click: find-in-page reaching into the shut panel asks to open it, and it is open.
|
|
107
|
+
const shown = open && !pending
|
|
96
108
|
return (
|
|
97
|
-
<Collapsible.Root open={
|
|
98
|
-
<SectionHeader title={title} chevron icon={icon} isExpanded={open} trailing={trailing} actions={actions} menu={menu} menuLabel={menuLabel} showActions={showActions} look={look} className="shrink-0" render={<Collapsible.Trigger />} />
|
|
109
|
+
<Collapsible.Root open={shown} onOpenChange={(next, details) => setOpen(pending && details.reason === 'trigger-press' ? !open : next)} className={cn('flex flex-col', className)}>
|
|
110
|
+
<SectionHeader title={title} chevron icon={icon} isExpanded={open} trailing={trailing} actions={actions} menu={menu} menuLabel={menuLabel} showActions={showActions} look={look} className="shrink-0" render={<Collapsible.Trigger aria-expanded={open} aria-busy={pending && open ? true : undefined} />} />
|
|
99
111
|
{/* The slide: Base UI measures the panel and writes its height to a
|
|
100
112
|
variable — `auto` again once the slide ends, so rows that arrive
|
|
101
113
|
later are not clipped — and the panel is 0 high on its opening frame
|
package/src/NavTree.mdx
CHANGED
|
@@ -54,7 +54,10 @@ rows to any depth.
|
|
|
54
54
|
skeleton under it once open, and `onOpenChange` says when to read them;
|
|
55
55
|
`childrenMessage` is the line under it. `onIntent` on a group says the
|
|
56
56
|
pointer rests on it or the keyboard reached it: read it then, so opening
|
|
57
|
-
it draws rows.
|
|
57
|
+
it draws rows. A `NavTreeSection` opened while its read is in flight takes
|
|
58
|
+
`pending`: its arrow turns and it opens once the rows are in, in one move,
|
|
59
|
+
instead of a skeleton the rows then replace; keep `loading` for a read
|
|
60
|
+
that turns out slow.
|
|
58
61
|
|
|
59
62
|
<Canvas of={NavTreeStories.ReadAsItOpens} />
|
|
60
63
|
|
package/src/NavTree.test.tsx
CHANGED
|
@@ -121,6 +121,16 @@ describe('NavTree drawn by the app', () => {
|
|
|
121
121
|
expect(screen.getByText('Item a')).not.toBeNull()
|
|
122
122
|
expect(screen.getByText('Nothing in this yet.')).not.toBeNull()
|
|
123
123
|
})
|
|
124
|
+
|
|
125
|
+
it('a pending NavTreeSection says open and busy, its rows shut until it is not (OPT-11)', () => {
|
|
126
|
+
const { rerender } = render(<NavTreeSection title="Group a" open pending><a href="#a">Item a</a></NavTreeSection>)
|
|
127
|
+
const heading = screen.getByRole('button', { name: 'Group a' })
|
|
128
|
+
expect(heading.getAttribute('aria-expanded')).toBe('true')
|
|
129
|
+
expect(heading.getAttribute('aria-busy')).toBe('true')
|
|
130
|
+
expect(screen.getByText('Item a').closest('[hidden]')).not.toBeNull()
|
|
131
|
+
rerender(<NavTreeSection title="Group a" open><a href="#a">Item a</a></NavTreeSection>)
|
|
132
|
+
expect(screen.getByText('Item a').closest('[hidden]')).toBeNull()
|
|
133
|
+
})
|
|
124
134
|
})
|
|
125
135
|
|
|
126
136
|
describe('NavTree marks its groups', () => {
|
package/src/NavTree.tsx
CHANGED
|
@@ -186,6 +186,12 @@ export interface NavTreeSectionProps {
|
|
|
186
186
|
onIntent?: () => void
|
|
187
187
|
/** Its rows are being read: a skeleton in their place. */
|
|
188
188
|
loading?: boolean
|
|
189
|
+
/**
|
|
190
|
+
* Opened, and its rows are being read: the arrow turns and the group stays
|
|
191
|
+
* shut until they are in, then opens once — `CollapsibleSection`'s. For a
|
|
192
|
+
* read that is usually quick; a slow one is `loading`'s skeleton.
|
|
193
|
+
*/
|
|
194
|
+
pending?: boolean
|
|
189
195
|
/** Remember it open or closed in this browser, under this key. */
|
|
190
196
|
storageKey?: string
|
|
191
197
|
/** The rows: `NavItem`s. */
|
|
@@ -199,7 +205,7 @@ export interface NavTreeSectionProps {
|
|
|
199
205
|
* `groups`; an app whose groups each read their own data draws them itself,
|
|
200
206
|
* as `NavTree`'s children.
|
|
201
207
|
*/
|
|
202
|
-
export function NavTreeSection({ id, title, message, loading = false, trailing, actions, menu, icon, defaultOpen = true, open, onOpenChange, storageKey, onIntent, children }: NavTreeSectionProps) {
|
|
208
|
+
export function NavTreeSection({ id, title, message, loading = false, pending, trailing, actions, menu, icon, defaultOpen = true, open, onOpenChange, storageKey, onIntent, children }: NavTreeSectionProps) {
|
|
203
209
|
const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)
|
|
204
210
|
useEffect(() => () => clearTimeout(timer.current), [])
|
|
205
211
|
const intent = onIntent
|
|
@@ -225,6 +231,7 @@ export function NavTreeSection({ id, title, message, loading = false, trailing,
|
|
|
225
231
|
defaultOpen={defaultOpen}
|
|
226
232
|
open={open}
|
|
227
233
|
onOpenChange={onOpenChange}
|
|
234
|
+
pending={pending}
|
|
228
235
|
storageKey={storageKey}
|
|
229
236
|
trailing={trailing}
|
|
230
237
|
actions={actions}
|
package/src/RichText.tsx
CHANGED
|
@@ -95,9 +95,9 @@ const RICH_TEXT_CLASSES = {
|
|
|
95
95
|
/* The line in the muted text grey, not the border grey: a border grey was 1.3 : 1 in Leaf (Katerina, 9 October). */
|
|
96
96
|
// eslint-disable-next-line token-spacing/no-restricted-classes -- @estiva-escape: the quote line is Peek's, 3px, between the ramp's 2 and 4
|
|
97
97
|
quote: '[&_blockquote>p]:m-0 [&_blockquote]:border-l-[3px] [&_blockquote]:border-text-muted [&_blockquote]:pl-2.5',
|
|
98
|
-
/* Code in a sentence
|
|
98
|
+
/* Code in a sentence: the code fill and a thin border, in the heading colour (Katerina, 9 October: option B; the amber of 0.64.0 was too much). */
|
|
99
99
|
// eslint-disable-next-line token-values/no-restricted-classes -- @estiva-escape: code is 0.85 of the text around it, so it scales with a heading and with `small`; a named size is fixed
|
|
100
|
-
code: '[&_: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]:
|
|
100
|
+
code: '[&_: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',
|
|
101
101
|
/* 12px either side, 10px above and below, looser lines than the text (Katerina, 9 October; 8px all round before). */
|
|
102
102
|
// eslint-disable-next-line token-values/no-restricted-classes -- @estiva-escape: code is 0.85 of the text around it; the code inside the block is the block's own size, not 0.85 of it again
|
|
103
103
|
codeBlock: '[&_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',
|
package/src/codeColours.ts
CHANGED
|
@@ -11,8 +11,16 @@ import { common, createLowlight } from 'lowlight'
|
|
|
11
11
|
*
|
|
12
12
|
* `common` is highlight.js's 37 everyday languages. A language outside them, or
|
|
13
13
|
* none, leaves the code in one colour.
|
|
14
|
+
*
|
|
15
|
+
* Made the first time code is coloured, not when the package loads: a call at
|
|
16
|
+
* the top of the file is kept by every app's bundler, so an app that never draws
|
|
17
|
+
* code carried highlight.js too (measured: an app importing only `Link` was
|
|
18
|
+
* 55 KB gzipped).
|
|
14
19
|
*/
|
|
15
|
-
|
|
20
|
+
let instance: ReturnType<typeof createLowlight> | undefined
|
|
21
|
+
export function lowlight() {
|
|
22
|
+
return (instance ??= createLowlight(common))
|
|
23
|
+
}
|
|
16
24
|
|
|
17
25
|
interface HastNode {
|
|
18
26
|
type: string
|
|
@@ -28,6 +36,6 @@ function draw(node: HastNode, key: number): ReactNode {
|
|
|
28
36
|
|
|
29
37
|
/** The code, its words wrapped in highlight.js's classes; the text as it is when the language is unknown. */
|
|
30
38
|
export function codeColours(text: string, language?: string): ReactNode {
|
|
31
|
-
if (!language || !lowlight.registered(language)) return text
|
|
32
|
-
return (lowlight.highlight(language, text).children as HastNode[]).map(draw)
|
|
39
|
+
if (!language || !lowlight().registered(language)) return text
|
|
40
|
+
return (lowlight().highlight(language, text).children as HastNode[]).map(draw)
|
|
33
41
|
}
|
package/tailwind-preset.js
CHANGED
|
@@ -155,7 +155,6 @@ export default {
|
|
|
155
155
|
'bg-tooltip-key': 'var(--bg-tooltip-key)',
|
|
156
156
|
'bg-field': 'var(--bg-field)',
|
|
157
157
|
'bg-code': 'var(--bg-code)',
|
|
158
|
-
'text-code': 'var(--text-code)',
|
|
159
158
|
'syntax-keyword': 'var(--syntax-keyword)',
|
|
160
159
|
'syntax-function': 'var(--syntax-function)',
|
|
161
160
|
'syntax-constant': 'var(--syntax-constant)',
|
package/tokens.css
CHANGED
|
@@ -101,8 +101,6 @@
|
|
|
101
101
|
/* Code, in a sentence and as a block, and a table's header row (RichText, UIG-30).
|
|
102
102
|
Here, the hover fill: bg-active, #D4D4D8, was the darkest thing on a white card (Katerina, 28 September). */
|
|
103
103
|
--bg-code: #E9E9EB;
|
|
104
|
-
/* Inline code's text: amber, on --bg-code (Katerina, 9 October: option I). Darker than the warning amber, which is 3.8 : 1 on the code fill; this is 4.8. */
|
|
105
|
-
--text-code: #855f00;
|
|
106
104
|
/* Colours inside a code block, by language (Katerina, 9 October). GitHub's light set; the keyword one shade darker (#cf222e is 4.4 : 1 on our fill, this 4.9). */
|
|
107
105
|
--syntax-keyword: #c21f2b;
|
|
108
106
|
--syntax-function: #6639ba;
|
|
@@ -194,8 +192,6 @@
|
|
|
194
192
|
/* Code, in a sentence and as a block, and a table's header row (RichText, UIG-30).
|
|
195
193
|
Here, bg-active, as Peek draws code (Katerina, 28 September). */
|
|
196
194
|
--bg-code: #2D2D31;
|
|
197
|
-
/* Inline code's text: amber, on --bg-code (Katerina, 9 October: option I). Amber 400, as on GitHub's dark ground. */
|
|
198
|
-
--text-code: #fbbf24;
|
|
199
195
|
/* Colours inside a code block, by language (Katerina, 9 October). GitHub's dark set. */
|
|
200
196
|
--syntax-keyword: #ff7b72;
|
|
201
197
|
--syntax-function: #d2a8ff;
|
|
@@ -291,8 +287,6 @@
|
|
|
291
287
|
/* Code, in a sentence and as a block, and a table's header row (RichText, UIG-30).
|
|
292
288
|
Here, bg-active, as Peek draws code (Katerina, 28 September). */
|
|
293
289
|
--bg-code: rgba(255, 255, 255, 0.08);
|
|
294
|
-
/* Inline code's text: amber, on --bg-code (Katerina, 9 October: option I). Signal's warning amber. */
|
|
295
|
-
--text-code: #ffb020;
|
|
296
290
|
/* Colours inside a code block, by language (Katerina, 9 October). GitHub's dark set. */
|
|
297
291
|
--syntax-keyword: #ff7b72;
|
|
298
292
|
--syntax-function: #d2a8ff;
|
|
@@ -402,8 +396,6 @@
|
|
|
402
396
|
/* Code, in a sentence and as a block, and a table's header row (RichText, UIG-30).
|
|
403
397
|
Here, bg-active, as Peek draws code (Katerina, 28 September). */
|
|
404
398
|
--bg-code: rgba(255, 255, 255, 0.08);
|
|
405
|
-
/* Inline code's text: amber, on --bg-code (Katerina, 9 October: option I). Ship's warning amber. */
|
|
406
|
-
--text-code: #e0b04a;
|
|
407
399
|
/* Colours inside a code block, by language (Katerina, 9 October). GitHub's dark set. */
|
|
408
400
|
--syntax-keyword: #ff7b72;
|
|
409
401
|
--syntax-function: #d2a8ff;
|
|
@@ -505,8 +497,6 @@
|
|
|
505
497
|
/* Code, in a sentence and as a block, and a table's header row (RichText, UIG-30).
|
|
506
498
|
Here, the inset fill: lighter than bg-active on a white card (Katerina, 28 September). */
|
|
507
499
|
--bg-code: #e9e9ea;
|
|
508
|
-
/* Inline code's text: amber, on --bg-code (Katerina, 9 October: option I). Darker than Leaf's warning amber (#967000, 3.8 : 1 on the code fill); this is 4.8. */
|
|
509
|
-
--text-code: #855f00;
|
|
510
500
|
/* Colours inside a code block, by language (Katerina, 9 October). GitHub's light set; the keyword one shade darker (#cf222e is 4.4 : 1 on our fill, this 4.9). */
|
|
511
501
|
--syntax-keyword: #c21f2b;
|
|
512
502
|
--syntax-function: #6639ba;
|