@scalewing/react 1.41.0 → 1.42.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/CHANGELOG.md +14 -0
- package/README.md +120 -1
- package/dist/components/Article.d.ts +60 -0
- package/dist/components/Article.js +42 -0
- package/dist/components/DocumentViewer.d.ts +41 -0
- package/dist/components/DocumentViewer.js +72 -0
- package/dist/components/FileField.d.ts +44 -0
- package/dist/components/FileField.js +66 -0
- package/dist/components/ListRow.d.ts +23 -2
- package/dist/components/ListRow.js +17 -17
- package/dist/components/MarkdownView.d.ts +39 -0
- package/dist/components/MarkdownView.js +30 -0
- package/dist/components/NavCount.d.ts +15 -2
- package/dist/components/NavCount.js +16 -6
- package/dist/components/chart/use-chart-width.js +2 -24
- package/dist/components/document-viewer/document-viewer-labels.d.ts +23 -0
- package/dist/components/document-viewer/document-viewer-labels.js +23 -0
- package/dist/components/document-viewer/page-box.d.ts +8 -0
- package/dist/components/document-viewer/page-box.js +12 -0
- package/dist/components/document-viewer/pdf-document.d.ts +32 -0
- package/dist/components/document-viewer/pdf-document.js +66 -0
- package/dist/components/document-viewer/pdf-options.d.ts +36 -0
- package/dist/components/document-viewer/pdf-options.js +46 -0
- package/dist/components/document-viewer/render-pdf-page.d.ts +20 -0
- package/dist/components/document-viewer/render-pdf-page.js +38 -0
- package/dist/components/document-viewer/scroll-chain.d.ts +6 -0
- package/dist/components/document-viewer/scroll-chain.js +23 -0
- package/dist/components/document-viewer/use-error-report.d.ts +5 -0
- package/dist/components/document-viewer/use-error-report.js +13 -0
- package/dist/components/document-viewer/use-page-render.d.ts +21 -0
- package/dist/components/document-viewer/use-page-render.js +70 -0
- package/dist/components/document-viewer/use-pdf-document.d.ts +22 -0
- package/dist/components/document-viewer/use-pdf-document.js +47 -0
- package/dist/components/document-viewer/use-pinch-zoom.d.ts +12 -0
- package/dist/components/document-viewer/use-pinch-zoom.js +67 -0
- package/dist/components/document-viewer/use-zoom.d.ts +23 -0
- package/dist/components/document-viewer/use-zoom.js +70 -0
- package/dist/components/document-viewer/zoom.d.ts +29 -0
- package/dist/components/document-viewer/zoom.js +37 -0
- package/dist/components/file-field/file-field-checks.d.ts +13 -0
- package/dist/components/file-field/file-field-checks.js +21 -0
- package/dist/components/file-field/use-file-drop.d.ts +34 -0
- package/dist/components/file-field/use-file-drop.js +78 -0
- package/dist/components/file-field/use-swap-focus.d.ts +15 -0
- package/dist/components/file-field/use-swap-focus.js +40 -0
- package/dist/components/list/ListRowContent.d.ts +6 -2
- package/dist/components/list/ListRowContent.js +5 -3
- package/dist/components/list/ListRowItem.d.ts +10 -0
- package/dist/components/list/ListRowItem.js +17 -0
- package/dist/components/list/row-naming.d.ts +17 -0
- package/dist/components/list/row-naming.js +19 -0
- package/dist/components/list/row-slot.d.ts +8 -0
- package/dist/components/list/row-slot.js +12 -0
- package/dist/components/markdown/markdown-limits.d.ts +14 -0
- package/dist/components/markdown/markdown-limits.js +14 -0
- package/dist/components/markdown/markdown-model.d.ts +94 -0
- package/dist/components/markdown/markdown-model.js +8 -0
- package/dist/components/markdown/markdown-options.d.ts +18 -0
- package/dist/components/markdown/markdown-options.js +10 -0
- package/dist/components/markdown/markdown-rules.d.ts +28 -0
- package/dist/components/markdown/markdown-rules.js +81 -0
- package/dist/components/markdown/markdown-text.d.ts +17 -0
- package/dist/components/markdown/markdown-text.js +86 -0
- package/dist/components/markdown/parse-markdown.d.ts +4 -0
- package/dist/components/markdown/parse-markdown.js +21 -0
- package/dist/components/markdown/read-blocks.d.ts +8 -0
- package/dist/components/markdown/read-blocks.js +168 -0
- package/dist/components/markdown/read-inlines.d.ts +12 -0
- package/dist/components/markdown/read-inlines.js +126 -0
- package/dist/components/markdown/read-markdown.d.ts +9 -0
- package/dist/components/markdown/read-markdown.js +27 -0
- package/dist/components/markdown/reading-context.d.ts +18 -0
- package/dist/components/markdown/reading-context.js +35 -0
- package/dist/components/markdown/render-markdown.d.ts +10 -0
- package/dist/components/markdown/render-markdown.js +52 -0
- package/dist/components/use-element-width.d.ts +11 -0
- package/dist/components/use-element-width.js +38 -0
- package/dist/css/css-article.d.ts +2 -0
- package/dist/css/css-article.js +110 -0
- package/dist/css/css-components.js +12 -0
- package/dist/css/css-count-pill.js +14 -1
- package/dist/css/css-document-viewer.d.ts +2 -0
- package/dist/css/css-document-viewer.js +186 -0
- package/dist/css/css-file-field.d.ts +2 -0
- package/dist/css/css-file-field.js +180 -0
- package/dist/css/css-list-row-trailing.d.ts +2 -0
- package/dist/css/css-list-row-trailing.js +91 -0
- package/dist/css/css-list.js +5 -1
- package/dist/css/css-markdown.d.ts +2 -0
- package/dist/css/css-markdown.js +144 -0
- package/dist/css/css-variables.js +1 -0
- package/dist/css/stylesheet.js +8 -0
- package/dist/document-viewer-worker.d.ts +9 -0
- package/dist/document-viewer-worker.js +9 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +5 -1
- package/dist/list-options.d.ts +5 -2
- package/dist/list-options.js +7 -2
- package/dist/styles.css +504 -0
- package/package.json +10 -2
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { breakpointQuery } from './breakpoints.js';
|
|
3
|
+
import { quietFill } from './quiet-fill.js';
|
|
4
|
+
const label = typographyVariants.label;
|
|
5
|
+
/** How much accent tints a selection of the page's text, in percent. */
|
|
6
|
+
const selectionTint = 30;
|
|
7
|
+
/*
|
|
8
|
+
* The viewer: a quiet grey stage at the large radius holding the page,
|
|
9
|
+
* and under it the page steps around "Page n of m". The stage scrolls
|
|
10
|
+
* sideways when the page is zoomed past its width; it only pans, so two
|
|
11
|
+
* fingers zoom the page, not the screen. The page is centred in it with a
|
|
12
|
+
* space-5 margin (space-3 on a phone), on the surface with the small
|
|
13
|
+
* elevation until PDF.js paints it.
|
|
14
|
+
*/
|
|
15
|
+
function stageRules() {
|
|
16
|
+
return `.sw-document-viewer {
|
|
17
|
+
background: ${quietFill};
|
|
18
|
+
border-radius: var(--sw-radius-lg);
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
min-width: 0;
|
|
22
|
+
padding-block-end: var(--sw-space-4);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.sw-document-viewer-stage {
|
|
26
|
+
box-sizing: border-box;
|
|
27
|
+
min-width: 0;
|
|
28
|
+
overflow-x: auto;
|
|
29
|
+
overscroll-behavior-x: contain;
|
|
30
|
+
padding: var(--sw-space-5);
|
|
31
|
+
touch-action: pan-x pan-y;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@media ${breakpointQuery('below', 'md')} {
|
|
35
|
+
.sw-document-viewer-stage { padding: var(--sw-space-3); }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.sw-document-viewer-stage:focus { outline: none; }
|
|
39
|
+
|
|
40
|
+
.sw-document-viewer-stage:focus-visible {
|
|
41
|
+
border-radius: var(--sw-radius-lg);
|
|
42
|
+
outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
|
|
43
|
+
outline-offset: calc(-1 * var(--sw-focus-ring-width));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.sw-document-viewer-page {
|
|
47
|
+
aspect-ratio: 1 / var(--sw-document-page-aspect);
|
|
48
|
+
background: var(--sw-color-surface);
|
|
49
|
+
box-shadow: var(--sw-elevation-sm);
|
|
50
|
+
margin-inline: auto;
|
|
51
|
+
position: relative;
|
|
52
|
+
width: var(--sw-document-page-width);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.sw-document-viewer-page > canvas {
|
|
56
|
+
display: block;
|
|
57
|
+
height: 100%;
|
|
58
|
+
width: 100%;
|
|
59
|
+
}`;
|
|
60
|
+
}
|
|
61
|
+
/*
|
|
62
|
+
* The page's text, laid over the drawing by PDF.js's TextLayer: each run
|
|
63
|
+
* transparent at its place and size, so it is read by assistive
|
|
64
|
+
* technology and selected, never seen. These are the rules PDF.js's own
|
|
65
|
+
* viewer gives its text layer, at the scale the viewer sets
|
|
66
|
+
* (--total-scale-factor) with whole-pixel rounding; a selection shows in a
|
|
67
|
+
* tint of the accent.
|
|
68
|
+
*/
|
|
69
|
+
function textLayerRules() {
|
|
70
|
+
return `.sw-document-viewer-text {
|
|
71
|
+
--scale-round-x: 1px;
|
|
72
|
+
--scale-round-y: 1px;
|
|
73
|
+
--min-font-size: 1;
|
|
74
|
+
--text-scale-factor: calc(var(--total-scale-factor) * var(--min-font-size));
|
|
75
|
+
--min-font-size-inv: calc(1 / var(--min-font-size));
|
|
76
|
+
forced-color-adjust: none;
|
|
77
|
+
inset: 0;
|
|
78
|
+
letter-spacing: normal;
|
|
79
|
+
line-height: 1;
|
|
80
|
+
overflow: clip;
|
|
81
|
+
position: absolute;
|
|
82
|
+
text-align: initial;
|
|
83
|
+
text-size-adjust: none;
|
|
84
|
+
transform-origin: 0 0;
|
|
85
|
+
word-spacing: normal;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.sw-document-viewer-text :is(span, br) {
|
|
89
|
+
color: transparent;
|
|
90
|
+
cursor: text;
|
|
91
|
+
position: absolute;
|
|
92
|
+
transform-origin: 0% 0%;
|
|
93
|
+
user-select: text;
|
|
94
|
+
white-space: pre;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.sw-document-viewer-text > :not(.markedContent),
|
|
98
|
+
.sw-document-viewer-text .markedContent span:not(.markedContent) {
|
|
99
|
+
--font-height: 0;
|
|
100
|
+
--scale-x: 1;
|
|
101
|
+
--rotate: 0deg;
|
|
102
|
+
font-size: calc(var(--text-scale-factor) * var(--font-height));
|
|
103
|
+
transform: rotate(var(--rotate)) scaleX(var(--scale-x)) scale(var(--min-font-size-inv));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.sw-document-viewer-text .markedContent { display: contents; }
|
|
107
|
+
|
|
108
|
+
.sw-document-viewer-text ::selection {
|
|
109
|
+
background: color-mix(in srgb, var(--sw-color-accent) ${selectionTint}%, transparent);
|
|
110
|
+
color: transparent;
|
|
111
|
+
}`;
|
|
112
|
+
}
|
|
113
|
+
/*
|
|
114
|
+
* The steps are 48-point round neutral Buttons (spacing step 8) with the
|
|
115
|
+
* pager's private chevron, around the page words in label type; with one
|
|
116
|
+
* page only the words show. Loading and a failed page centre their words
|
|
117
|
+
* (and the consumer's actions) in the stage.
|
|
118
|
+
*/
|
|
119
|
+
function barRules() {
|
|
120
|
+
return `.sw-document-viewer-bar {
|
|
121
|
+
align-items: center;
|
|
122
|
+
display: flex;
|
|
123
|
+
gap: var(--sw-space-3);
|
|
124
|
+
justify-content: center;
|
|
125
|
+
padding-inline: var(--sw-space-3);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.sw-button.sw-document-viewer-step {
|
|
129
|
+
border-radius: var(--sw-radius-pill);
|
|
130
|
+
flex: none;
|
|
131
|
+
min-height: var(--sw-space-8);
|
|
132
|
+
min-width: var(--sw-space-8);
|
|
133
|
+
padding-inline: 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.sw-document-viewer-status {
|
|
137
|
+
font-family: var(--sw-font-sans);
|
|
138
|
+
font-size: ${label.fontSize}px;
|
|
139
|
+
font-variant-numeric: tabular-nums;
|
|
140
|
+
line-height: ${label.lineHeight}px;
|
|
141
|
+
text-align: center;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.sw-document-viewer-message {
|
|
145
|
+
align-items: center;
|
|
146
|
+
display: flex;
|
|
147
|
+
flex-direction: column;
|
|
148
|
+
gap: var(--sw-space-2);
|
|
149
|
+
justify-content: center;
|
|
150
|
+
min-height: calc(4 * var(--sw-space-8));
|
|
151
|
+
text-align: center;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.sw-document-viewer-actions {
|
|
155
|
+
display: flex;
|
|
156
|
+
flex-wrap: wrap;
|
|
157
|
+
gap: var(--sw-space-2);
|
|
158
|
+
justify-content: center;
|
|
159
|
+
margin-block-start: var(--sw-space-2);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@media (forced-colors: active) {
|
|
163
|
+
.sw-document-viewer { border: 1px solid CanvasText; }
|
|
164
|
+
.sw-document-viewer-page { outline: 1px solid CanvasText; }
|
|
165
|
+
}`;
|
|
166
|
+
}
|
|
167
|
+
export function cssDocumentViewerClasses() {
|
|
168
|
+
return `${stageRules()}
|
|
169
|
+
|
|
170
|
+
${textLayerRules()}
|
|
171
|
+
|
|
172
|
+
${barRules()}`;
|
|
173
|
+
}
|
|
174
|
+
export function documentViewerClassCatalog() {
|
|
175
|
+
return [
|
|
176
|
+
'sw-document-viewer',
|
|
177
|
+
'sw-document-viewer-stage',
|
|
178
|
+
'sw-document-viewer-page',
|
|
179
|
+
'sw-document-viewer-text',
|
|
180
|
+
'sw-document-viewer-bar',
|
|
181
|
+
'sw-document-viewer-step',
|
|
182
|
+
'sw-document-viewer-status',
|
|
183
|
+
'sw-document-viewer-message',
|
|
184
|
+
'sw-document-viewer-actions',
|
|
185
|
+
];
|
|
186
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { disabledControlSurface } from './css-document.js';
|
|
3
|
+
import { coarsePointerQuery, touchTarget } from './touch-target.js';
|
|
4
|
+
const label = typographyVariants.label;
|
|
5
|
+
const caption = typographyVariants.caption;
|
|
6
|
+
/*
|
|
7
|
+
* The frame holds the field's one file: empty, a wide zone on the subtle
|
|
8
|
+
* fill that opens the picker (the choose words in the text colour at
|
|
9
|
+
* label weight, as the accent falls under 4.5:1 on the subtle fill in
|
|
10
|
+
* some palettes, the drop words muted after them); chosen, a row on the surface
|
|
11
|
+
* with the consumer's mark, the file's name over its detail and the
|
|
12
|
+
* change button at the end. Both are a hairline frame at the medium
|
|
13
|
+
* radius. A file dragged over either draws the accent edge and tint. A
|
|
14
|
+
* chosen row too narrow for a long name and the button wraps the button
|
|
15
|
+
* under the name, at the row's end.
|
|
16
|
+
*/
|
|
17
|
+
function frameRules() {
|
|
18
|
+
return `.sw-file-field-frame {
|
|
19
|
+
border: 1px solid var(--sw-color-border);
|
|
20
|
+
border-radius: var(--sw-radius-md);
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
min-width: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.sw-file-field-empty { background: var(--sw-color-subtle); }
|
|
26
|
+
|
|
27
|
+
.sw-file-field-chosen {
|
|
28
|
+
align-items: center;
|
|
29
|
+
background: var(--sw-color-surface);
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-wrap: wrap;
|
|
32
|
+
gap: var(--sw-space-2) var(--sw-space-3);
|
|
33
|
+
padding: var(--sw-space-2) var(--sw-space-2) var(--sw-space-2) var(--sw-space-4);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.sw-field-invalid .sw-file-field-frame { border-color: var(--sw-color-danger); }
|
|
37
|
+
|
|
38
|
+
/* A drag wins over an error's edge: it says where the file goes. */
|
|
39
|
+
.sw-file-field-frame.sw-file-field-dragging {
|
|
40
|
+
background: var(--sw-color-accentSubtle);
|
|
41
|
+
border-color: var(--sw-color-accent);
|
|
42
|
+
outline: 1px solid var(--sw-color-accent);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* On the tint, muted words fall under 4.5:1 in light palettes: every word takes the text colour. */
|
|
46
|
+
.sw-file-field-dragging :is(.sw-file-field-choose, .sw-file-field-drop, .sw-file-field-detail, .sw-file-field-icon) {
|
|
47
|
+
color: var(--sw-color-text);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Disabled, the frame's hairline is dashed, as a disabled text control's. */
|
|
51
|
+
.sw-file-field-disabled { border-style: dashed; }`;
|
|
52
|
+
}
|
|
53
|
+
/*
|
|
54
|
+
* The empty zone is one button filling the frame, a space-6 of padding
|
|
55
|
+
* above and below its words, its focus ring inside the frame's edge. On a
|
|
56
|
+
* coarse pointer, where nothing is dragged, the drop words are left out.
|
|
57
|
+
*/
|
|
58
|
+
function zoneRules() {
|
|
59
|
+
return `.sw-file-field-zone {
|
|
60
|
+
align-items: center;
|
|
61
|
+
appearance: none;
|
|
62
|
+
background: transparent;
|
|
63
|
+
border: 0;
|
|
64
|
+
border-radius: inherit;
|
|
65
|
+
box-sizing: border-box;
|
|
66
|
+
color: var(--sw-color-text);
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
display: flex;
|
|
69
|
+
flex-wrap: wrap;
|
|
70
|
+
font-family: var(--sw-font-sans);
|
|
71
|
+
font-size: ${label.fontSize}px;
|
|
72
|
+
gap: var(--sw-space-1);
|
|
73
|
+
justify-content: center;
|
|
74
|
+
line-height: ${label.lineHeight}px;
|
|
75
|
+
margin: 0;
|
|
76
|
+
min-height: ${touchTarget};
|
|
77
|
+
padding: var(--sw-space-6) var(--sw-space-4);
|
|
78
|
+
text-align: center;
|
|
79
|
+
width: 100%;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.sw-file-field-zone:focus { outline: none; }
|
|
83
|
+
|
|
84
|
+
.sw-file-field-zone:focus-visible {
|
|
85
|
+
outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
|
|
86
|
+
outline-offset: calc(-1 * var(--sw-focus-ring-width));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.sw-file-field-choose {
|
|
90
|
+
color: var(--sw-color-text);
|
|
91
|
+
font-weight: ${label.fontWeight};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.sw-file-field-drop { color: var(--sw-color-muted); }
|
|
95
|
+
|
|
96
|
+
.sw-file-field-zone:disabled {
|
|
97
|
+
${disabledControlSurface}
|
|
98
|
+
border-radius: inherit;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.sw-file-field-zone:disabled .sw-file-field-choose { color: var(--sw-color-muted); }
|
|
102
|
+
|
|
103
|
+
@media ${coarsePointerQuery} {
|
|
104
|
+
.sw-file-field-drop { display: none; }
|
|
105
|
+
}`;
|
|
106
|
+
}
|
|
107
|
+
/*
|
|
108
|
+
* The chosen file: the mark, then the name over its detail (at least four
|
|
109
|
+
* space-8 wide before the button wraps under it), then the button.
|
|
110
|
+
*/
|
|
111
|
+
function fileRules() {
|
|
112
|
+
return `.sw-file-field-icon {
|
|
113
|
+
align-items: center;
|
|
114
|
+
color: var(--sw-color-muted);
|
|
115
|
+
display: flex;
|
|
116
|
+
flex: none;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.sw-file-field-file {
|
|
120
|
+
display: flex;
|
|
121
|
+
flex: 1 1 calc(4 * var(--sw-space-8));
|
|
122
|
+
flex-direction: column;
|
|
123
|
+
min-width: 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.sw-file-field-name {
|
|
127
|
+
font-size: ${label.fontSize}px;
|
|
128
|
+
font-weight: ${label.fontWeight};
|
|
129
|
+
line-height: ${label.lineHeight}px;
|
|
130
|
+
overflow-wrap: anywhere;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.sw-file-field-detail {
|
|
134
|
+
color: var(--sw-color-muted);
|
|
135
|
+
font-size: ${caption.fontSize}px;
|
|
136
|
+
line-height: ${caption.lineHeight}px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.sw-file-field-chosen > .sw-button {
|
|
140
|
+
flex: none;
|
|
141
|
+
margin-inline-start: auto;
|
|
142
|
+
}`;
|
|
143
|
+
}
|
|
144
|
+
/* Forced colours: system edges, Highlight for a drag, the button text colour for the words. */
|
|
145
|
+
function forcedColorRules() {
|
|
146
|
+
return `@media (forced-colors: active) {
|
|
147
|
+
.sw-file-field-frame { border-color: CanvasText; }
|
|
148
|
+
.sw-field-invalid .sw-file-field-frame { border-color: Mark; }
|
|
149
|
+
.sw-file-field-frame.sw-file-field-dragging { border-color: Highlight; outline-color: Highlight; }
|
|
150
|
+
.sw-file-field-choose { color: ButtonText; }
|
|
151
|
+
.sw-file-field-zone:disabled,
|
|
152
|
+
.sw-file-field-zone:disabled .sw-file-field-choose { color: GrayText; }
|
|
153
|
+
}`;
|
|
154
|
+
}
|
|
155
|
+
export function cssFileFieldClasses() {
|
|
156
|
+
return `${frameRules()}
|
|
157
|
+
|
|
158
|
+
${zoneRules()}
|
|
159
|
+
|
|
160
|
+
${fileRules()}
|
|
161
|
+
|
|
162
|
+
${forcedColorRules()}`;
|
|
163
|
+
}
|
|
164
|
+
export function fileFieldClassCatalog() {
|
|
165
|
+
return [
|
|
166
|
+
'sw-file-field',
|
|
167
|
+
'sw-file-field-frame',
|
|
168
|
+
'sw-file-field-empty',
|
|
169
|
+
'sw-file-field-chosen',
|
|
170
|
+
'sw-file-field-dragging',
|
|
171
|
+
'sw-file-field-disabled',
|
|
172
|
+
'sw-file-field-zone',
|
|
173
|
+
'sw-file-field-choose',
|
|
174
|
+
'sw-file-field-drop',
|
|
175
|
+
'sw-file-field-icon',
|
|
176
|
+
'sw-file-field-file',
|
|
177
|
+
'sw-file-field-name',
|
|
178
|
+
'sw-file-field-detail',
|
|
179
|
+
];
|
|
180
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { quietFill } from './quiet-fill.js';
|
|
2
|
+
/*
|
|
3
|
+
* The unread dot: an accent circle a space-2 across after the title's last
|
|
4
|
+
* word, on its line. It is drawn as a border, so forced colours keep it
|
|
5
|
+
* (in the text colour); the hidden words beside the title say what it is.
|
|
6
|
+
* Centred on the words' middle, as an inline mark.
|
|
7
|
+
*/
|
|
8
|
+
function unreadRules() {
|
|
9
|
+
return `.sw-list-row-unread {
|
|
10
|
+
border: calc(var(--sw-space-2) / 2) solid var(--sw-color-accent);
|
|
11
|
+
border-radius: var(--sw-radius-pill);
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
display: inline-block;
|
|
14
|
+
height: var(--sw-space-2);
|
|
15
|
+
margin-inline-start: var(--sw-space-2);
|
|
16
|
+
vertical-align: middle;
|
|
17
|
+
width: var(--sw-space-2);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@media (forced-colors: active) {
|
|
21
|
+
.sw-list-row-unread { border-color: CanvasText; }
|
|
22
|
+
}`;
|
|
23
|
+
}
|
|
24
|
+
/*
|
|
25
|
+
* The tag (a Badge, "Only in English") sits before the accessory, centred
|
|
26
|
+
* on the row's height and never shrunk or wrapped.
|
|
27
|
+
*/
|
|
28
|
+
function tagRules() {
|
|
29
|
+
return `.sw-list-row-tag {
|
|
30
|
+
align-self: center;
|
|
31
|
+
display: inline-flex;
|
|
32
|
+
flex: none;
|
|
33
|
+
white-space: nowrap;
|
|
34
|
+
}`;
|
|
35
|
+
}
|
|
36
|
+
/*
|
|
37
|
+
* A row with an action is the row's button or link followed by the
|
|
38
|
+
* action's control in one list item, the control centred on the row's
|
|
39
|
+
* height after it and outside its press area. The row ends a space-2
|
|
40
|
+
* before the control, and the control keeps the row's inline end padding
|
|
41
|
+
* after it (a space-4 in a panel, none in a plain list). Where :has() is
|
|
42
|
+
* supported, the hover fill spans the whole item, so the row and its
|
|
43
|
+
* control read as one line; elsewhere the row keeps its own fill.
|
|
44
|
+
*/
|
|
45
|
+
function actionRules() {
|
|
46
|
+
return `.sw-list-item-action {
|
|
47
|
+
align-items: center;
|
|
48
|
+
display: flex;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.sw-list-item-action > .sw-list-row {
|
|
52
|
+
flex: 1 1 auto;
|
|
53
|
+
min-width: 0;
|
|
54
|
+
padding-inline-end: var(--sw-space-2);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.sw-list-row-action {
|
|
58
|
+
display: inline-flex;
|
|
59
|
+
flex: none;
|
|
60
|
+
padding-inline-end: var(--sw-space-4);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.sw-list-group-plain .sw-list-row-action { padding-inline-end: 0; }
|
|
64
|
+
|
|
65
|
+
@supports selector(:has(*)) {
|
|
66
|
+
@media (hover: hover) {
|
|
67
|
+
.sw-list-item-action:has(> .sw-list-row-pressable:hover:not(.sw-list-row-disabled)) {
|
|
68
|
+
background: ${quietFill};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.sw-list-item-action > .sw-list-row-pressable:hover:not(.sw-list-row-disabled) {
|
|
72
|
+
background: transparent;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}`;
|
|
76
|
+
}
|
|
77
|
+
export function cssListRowTrailingClasses() {
|
|
78
|
+
return `${unreadRules()}
|
|
79
|
+
|
|
80
|
+
${tagRules()}
|
|
81
|
+
|
|
82
|
+
${actionRules()}`;
|
|
83
|
+
}
|
|
84
|
+
export function listRowTrailingClassCatalog() {
|
|
85
|
+
return [
|
|
86
|
+
'sw-list-row-unread',
|
|
87
|
+
'sw-list-row-tag',
|
|
88
|
+
'sw-list-item-action',
|
|
89
|
+
'sw-list-row-action',
|
|
90
|
+
];
|
|
91
|
+
}
|
package/dist/css/css-list.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
2
|
import { cssListRowClasses, listRowClassCatalog } from './css-list-row.js';
|
|
3
|
+
import { cssListRowTrailingClasses, listRowTrailingClassCatalog, } from './css-list-row-trailing.js';
|
|
3
4
|
import { blockEdgeShadeRules, scrollRegionRules } from './css-scroll-region.js';
|
|
4
5
|
const label = typographyVariants.label;
|
|
5
6
|
const caption = typographyVariants.caption;
|
|
@@ -69,7 +70,9 @@ export function cssListClasses() {
|
|
|
69
70
|
|
|
70
71
|
${boundedRules()}
|
|
71
72
|
|
|
72
|
-
${cssListRowClasses()}
|
|
73
|
+
${cssListRowClasses()}
|
|
74
|
+
|
|
75
|
+
${cssListRowTrailingClasses()}`;
|
|
73
76
|
}
|
|
74
77
|
export function listClassCatalog() {
|
|
75
78
|
return [
|
|
@@ -81,5 +84,6 @@ export function listClassCatalog() {
|
|
|
81
84
|
'sw-list-group-scroll',
|
|
82
85
|
'sw-list-group-footer',
|
|
83
86
|
...listRowClassCatalog(),
|
|
87
|
+
...listRowTrailingClassCatalog(),
|
|
84
88
|
];
|
|
85
89
|
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
const { body, title, label, caption } = typographyVariants;
|
|
3
|
+
/*
|
|
4
|
+
* A page of Markdown in body type: blocks a space-4 apart, a heading a
|
|
5
|
+
* space-6 below what comes before it and a space-2 above what follows.
|
|
6
|
+
* `#` is the title size, `##` body size and `###` label size, all at the
|
|
7
|
+
* title's weight. At zero specificity (`:where`), so a consumer's layout
|
|
8
|
+
* can still space the view itself.
|
|
9
|
+
*/
|
|
10
|
+
function flowRules() {
|
|
11
|
+
return `.sw-markdown {
|
|
12
|
+
color: var(--sw-color-text);
|
|
13
|
+
font-family: var(--sw-font-sans);
|
|
14
|
+
font-size: ${body.fontSize}px;
|
|
15
|
+
letter-spacing: ${body.letterSpacing}px;
|
|
16
|
+
line-height: ${body.lineHeight}px;
|
|
17
|
+
overflow-wrap: anywhere;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
:where(.sw-markdown) > *,
|
|
21
|
+
:where(.sw-markdown-quote) > *,
|
|
22
|
+
:where(.sw-markdown-list li) > * { margin-block: 0; }
|
|
23
|
+
|
|
24
|
+
:where(.sw-markdown, .sw-markdown-quote, .sw-markdown-list li) > * + * {
|
|
25
|
+
margin-block-start: var(--sw-space-4);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
:where(.sw-markdown) > * + .sw-markdown-heading { margin-block-start: var(--sw-space-6); }
|
|
29
|
+
:where(.sw-markdown) > .sw-markdown-heading + * { margin-block-start: var(--sw-space-2); }
|
|
30
|
+
|
|
31
|
+
.sw-markdown-heading {
|
|
32
|
+
color: var(--sw-color-text);
|
|
33
|
+
font-weight: ${title.fontWeight};
|
|
34
|
+
scroll-margin-block-start: var(--sw-space-6);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.sw-markdown-heading-1 {
|
|
38
|
+
font-size: ${title.fontSize}px;
|
|
39
|
+
letter-spacing: ${title.letterSpacing}px;
|
|
40
|
+
line-height: ${title.lineHeight}px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.sw-markdown-heading-2 {
|
|
44
|
+
font-size: ${body.fontSize}px;
|
|
45
|
+
line-height: ${body.lineHeight}px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.sw-markdown-heading-3 {
|
|
49
|
+
font-size: ${label.fontSize}px;
|
|
50
|
+
letter-spacing: ${label.letterSpacing}px;
|
|
51
|
+
line-height: ${label.lineHeight}px;
|
|
52
|
+
}`;
|
|
53
|
+
}
|
|
54
|
+
/*
|
|
55
|
+
* Lists hang their markers in the page's margin a space-5 in; a tight
|
|
56
|
+
* list's items are a space-2 apart. A link is the accent, underlined, so
|
|
57
|
+
* it never depends on colour alone, and thickens to the focus ring's
|
|
58
|
+
* width while hovered. In the highlighted box, whose tint neither the
|
|
59
|
+
* accent nor the muted colour clears at 4.5:1 in every palette, links
|
|
60
|
+
* (still underlined) and photo captions are the text colour.
|
|
61
|
+
*/
|
|
62
|
+
function inlineRules() {
|
|
63
|
+
return `.sw-markdown-list {
|
|
64
|
+
padding-inline-start: var(--sw-space-5);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.sw-markdown-list > li + li { margin-block-start: var(--sw-space-2); }
|
|
68
|
+
|
|
69
|
+
[data-theme] .sw-markdown-link {
|
|
70
|
+
color: var(--sw-color-accent);
|
|
71
|
+
text-decoration-line: underline;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
[data-theme] .sw-markdown-link:hover {
|
|
75
|
+
text-decoration-thickness: var(--sw-focus-ring-width);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
[data-theme] .sw-markdown-quote :is(.sw-markdown-link, .sw-markdown-caption) {
|
|
79
|
+
color: var(--sw-color-text);
|
|
80
|
+
}`;
|
|
81
|
+
}
|
|
82
|
+
/*
|
|
83
|
+
* A block quote is the highlighted box: the accent's subtle tint with an
|
|
84
|
+
* accent bar at its start, at the small radius. A photo fills the page's
|
|
85
|
+
* width at the medium radius, its caption muted under it.
|
|
86
|
+
*/
|
|
87
|
+
function boxRules() {
|
|
88
|
+
return `.sw-markdown-quote {
|
|
89
|
+
background: var(--sw-color-accentSubtle);
|
|
90
|
+
border-inline-start: var(--sw-space-1) solid var(--sw-color-accent);
|
|
91
|
+
border-radius: var(--sw-radius-sm);
|
|
92
|
+
margin-inline: 0;
|
|
93
|
+
padding: var(--sw-space-3) var(--sw-space-4);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.sw-markdown-figure {
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-direction: column;
|
|
99
|
+
gap: var(--sw-space-2);
|
|
100
|
+
margin-inline: 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.sw-markdown-image {
|
|
104
|
+
border-radius: var(--sw-radius-md);
|
|
105
|
+
display: block;
|
|
106
|
+
height: auto;
|
|
107
|
+
width: 100%;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.sw-markdown-caption {
|
|
111
|
+
color: var(--sw-color-muted);
|
|
112
|
+
font-size: ${caption.fontSize}px;
|
|
113
|
+
letter-spacing: ${caption.letterSpacing}px;
|
|
114
|
+
line-height: ${caption.lineHeight}px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@media (forced-colors: active) {
|
|
118
|
+
.sw-markdown-quote { border: 1px solid CanvasText; border-inline-start-width: var(--sw-space-1); }
|
|
119
|
+
}`;
|
|
120
|
+
}
|
|
121
|
+
export function cssMarkdownClasses() {
|
|
122
|
+
return `${flowRules()}
|
|
123
|
+
|
|
124
|
+
${inlineRules()}
|
|
125
|
+
|
|
126
|
+
${boxRules()}`;
|
|
127
|
+
}
|
|
128
|
+
export function markdownClassCatalog() {
|
|
129
|
+
return [
|
|
130
|
+
'sw-markdown',
|
|
131
|
+
'sw-markdown-paragraph',
|
|
132
|
+
'sw-markdown-heading',
|
|
133
|
+
'sw-markdown-heading-1',
|
|
134
|
+
'sw-markdown-heading-2',
|
|
135
|
+
'sw-markdown-heading-3',
|
|
136
|
+
'sw-markdown-list',
|
|
137
|
+
'sw-markdown-item-text',
|
|
138
|
+
'sw-markdown-link',
|
|
139
|
+
'sw-markdown-quote',
|
|
140
|
+
'sw-markdown-figure',
|
|
141
|
+
'sw-markdown-image',
|
|
142
|
+
'sw-markdown-caption',
|
|
143
|
+
];
|
|
144
|
+
}
|
package/dist/css/stylesheet.js
CHANGED
|
@@ -7,7 +7,11 @@ import { switchClassCatalog } from './css-switch.js';
|
|
|
7
7
|
import { dateFieldClassCatalog } from './css-date-field.js';
|
|
8
8
|
import { calendarButtonClassCatalog } from './css-calendar-button.js';
|
|
9
9
|
import { dateRangeClassCatalog } from './css-date-range.js';
|
|
10
|
+
import { fileFieldClassCatalog } from './css-file-field.js';
|
|
11
|
+
import { articleClassCatalog } from './css-article.js';
|
|
12
|
+
import { documentViewerClassCatalog } from './css-document-viewer.js';
|
|
10
13
|
import { listClassCatalog } from './css-list.js';
|
|
14
|
+
import { markdownClassCatalog } from './css-markdown.js';
|
|
11
15
|
import { countPillClassCatalog } from './css-count-pill.js';
|
|
12
16
|
import { checkboxClassCatalog } from './css-checkbox.js';
|
|
13
17
|
import { radioGroupClassCatalog } from './css-radio-group.js';
|
|
@@ -104,6 +108,10 @@ export function utilityClassCatalog() {
|
|
|
104
108
|
...calendarButtonClassCatalog(),
|
|
105
109
|
...dateRangeClassCatalog(),
|
|
106
110
|
...listClassCatalog(),
|
|
111
|
+
...fileFieldClassCatalog(),
|
|
112
|
+
...articleClassCatalog(),
|
|
113
|
+
...documentViewerClassCatalog(),
|
|
114
|
+
...markdownClassCatalog(),
|
|
107
115
|
...countPillClassCatalog(),
|
|
108
116
|
...checkboxClassCatalog(),
|
|
109
117
|
...radioGroupClassCatalog(),
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PDF.js worker for `DocumentViewer`, at the exact PDF.js version
|
|
3
|
+
* Scalewing pins and from the same legacy build: a module worker entry
|
|
4
|
+
* that starts PDF.js's worker on import. A consumer bundles it as a worker
|
|
5
|
+
* and passes its URL as `workerSrc`, such as Vite's
|
|
6
|
+
* `import workerSrc from '@scalewing/react/document-viewer-worker?worker&url'`,
|
|
7
|
+
* so the viewer and its worker are always the same version.
|
|
8
|
+
*/
|
|
9
|
+
import 'pdfjs-dist/legacy/build/pdf.worker.min.mjs';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PDF.js worker for `DocumentViewer`, at the exact PDF.js version
|
|
3
|
+
* Scalewing pins and from the same legacy build: a module worker entry
|
|
4
|
+
* that starts PDF.js's worker on import. A consumer bundles it as a worker
|
|
5
|
+
* and passes its URL as `workerSrc`, such as Vite's
|
|
6
|
+
* `import workerSrc from '@scalewing/react/document-viewer-worker?worker&url'`,
|
|
7
|
+
* so the viewer and its worker are always the same version.
|
|
8
|
+
*/
|
|
9
|
+
import 'pdfjs-dist/legacy/build/pdf.worker.min.mjs';
|