@tldraw/editor 3.12.0-canary.d81bcb86d4e7 → 3.12.0-canary.e333011facbe
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-cjs/index.d.ts +40 -3
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/TldrawEditor.js +4 -0
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +24 -8
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/exports/StyleEmbedder.js +19 -5
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/cssRules.js +127 -0
- package/dist-cjs/lib/exports/cssRules.js.map +7 -0
- package/dist-cjs/lib/exports/parseCss.js +0 -69
- package/dist-cjs/lib/exports/parseCss.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +40 -3
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/TldrawEditor.mjs +4 -0
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +24 -8
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/exports/StyleEmbedder.mjs +21 -12
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/cssRules.mjs +107 -0
- package/dist-esm/lib/exports/cssRules.mjs.map +7 -0
- package/dist-esm/lib/exports/parseCss.mjs +0 -69
- package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +7 -7
- package/src/lib/TldrawEditor.tsx +27 -1
- package/src/lib/editor/Editor.ts +52 -8
- package/src/lib/exports/StyleEmbedder.ts +25 -15
- package/src/lib/exports/cssRules.ts +126 -0
- package/src/lib/exports/parseCss.ts +0 -79
- package/src/version.ts +3 -3
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { assertExists, objectMapValues, uniqueId } from '@tldraw/utils'
|
|
1
|
+
import { assertExists, getOwnProperty, objectMapValues, uniqueId } from '@tldraw/utils'
|
|
2
2
|
import { FontEmbedder } from './FontEmbedder'
|
|
3
|
+
import { ReadonlyStyles, Styles, cssRules } from './cssRules'
|
|
3
4
|
import {
|
|
4
5
|
elementStyle,
|
|
5
6
|
getComputedStyle,
|
|
@@ -7,15 +8,8 @@ import {
|
|
|
7
8
|
getRenderedChildren,
|
|
8
9
|
} from './domUtils'
|
|
9
10
|
import { resourceToDataUrl } from './fetchCache'
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
isPropertyInherited,
|
|
13
|
-
parseCssValueUrls,
|
|
14
|
-
shouldIncludeCssProperty,
|
|
15
|
-
} from './parseCss'
|
|
16
|
-
|
|
17
|
-
type Styles = { [K in string]?: string }
|
|
18
|
-
type ReadonlyStyles = { readonly [K in string]?: string }
|
|
11
|
+
import { parseCssValueUrls, shouldIncludeCssProperty } from './parseCss'
|
|
12
|
+
|
|
19
13
|
const NO_STYLES = {} as const
|
|
20
14
|
|
|
21
15
|
interface ElementStyleInfo {
|
|
@@ -239,15 +233,22 @@ function styleFromComputedStyleMap(
|
|
|
239
233
|
{ defaultStyles, parentStyles }: ReadStyleOpts
|
|
240
234
|
) {
|
|
241
235
|
const styles: Record<string, string> = {}
|
|
236
|
+
const currentColor = style.get('color')?.toString() || ''
|
|
237
|
+
const ruleOptions = {
|
|
238
|
+
currentColor,
|
|
239
|
+
parentStyles,
|
|
240
|
+
defaultStyles,
|
|
241
|
+
getStyle: (property: string) => style.get(property)?.toString() ?? '',
|
|
242
|
+
}
|
|
242
243
|
for (const property of style.keys()) {
|
|
243
244
|
if (!shouldIncludeCssProperty(property)) continue
|
|
244
245
|
|
|
245
246
|
const value = style.get(property)!.toString()
|
|
246
247
|
|
|
247
248
|
if (defaultStyles[property] === value) continue
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
|
|
250
|
+
const rule = getOwnProperty(cssRules, property)
|
|
251
|
+
if (rule && rule(value, property, ruleOptions)) continue
|
|
251
252
|
|
|
252
253
|
styles[property] = value
|
|
253
254
|
}
|
|
@@ -260,14 +261,23 @@ function styleFromComputedStyle(
|
|
|
260
261
|
{ defaultStyles, parentStyles }: ReadStyleOpts
|
|
261
262
|
) {
|
|
262
263
|
const styles: Record<string, string> = {}
|
|
264
|
+
const currentColor = style.color
|
|
265
|
+
const ruleOptions = {
|
|
266
|
+
currentColor,
|
|
267
|
+
parentStyles,
|
|
268
|
+
defaultStyles,
|
|
269
|
+
getStyle: (property: string) => style.getPropertyValue(property),
|
|
270
|
+
}
|
|
271
|
+
|
|
263
272
|
for (const property in style) {
|
|
264
273
|
if (!shouldIncludeCssProperty(property)) continue
|
|
265
274
|
|
|
266
275
|
const value = style.getPropertyValue(property)
|
|
267
276
|
|
|
268
277
|
if (defaultStyles[property] === value) continue
|
|
269
|
-
|
|
270
|
-
|
|
278
|
+
|
|
279
|
+
const rule = getOwnProperty(cssRules, property)
|
|
280
|
+
if (rule && rule(value, property, ruleOptions)) continue
|
|
271
281
|
|
|
272
282
|
styles[property] = value
|
|
273
283
|
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
export type Styles = { [K in string]?: string }
|
|
2
|
+
export type ReadonlyStyles = { readonly [K in string]?: string }
|
|
3
|
+
|
|
4
|
+
type CanSkipRule = (
|
|
5
|
+
value: string,
|
|
6
|
+
property: string,
|
|
7
|
+
options: {
|
|
8
|
+
getStyle(property: string): string
|
|
9
|
+
parentStyles: ReadonlyStyles
|
|
10
|
+
defaultStyles: ReadonlyStyles
|
|
11
|
+
currentColor: string
|
|
12
|
+
}
|
|
13
|
+
) => boolean
|
|
14
|
+
|
|
15
|
+
const isCoveredByCurrentColor: CanSkipRule = (value, property, { currentColor }) => {
|
|
16
|
+
return value === 'currentColor' || value === currentColor
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const isInherited: CanSkipRule = (value, property, { parentStyles }) => {
|
|
20
|
+
return parentStyles[property] === value
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// see comment below about why we exclude border styles
|
|
24
|
+
const isExcludedBorder =
|
|
25
|
+
(borderDirection: string): CanSkipRule =>
|
|
26
|
+
(value, property, { getStyle }) => {
|
|
27
|
+
const borderWidth = getStyle(`border-${borderDirection}-width`)
|
|
28
|
+
const borderStyle = getStyle(`border-${borderDirection}-style`)
|
|
29
|
+
|
|
30
|
+
if (borderWidth === '0px') return true
|
|
31
|
+
if (borderStyle === 'none') return true
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const cssRules = {
|
|
36
|
+
// currentColor properties:
|
|
37
|
+
'border-block-end-color': isCoveredByCurrentColor,
|
|
38
|
+
'border-block-start-color': isCoveredByCurrentColor,
|
|
39
|
+
'border-bottom-color': isCoveredByCurrentColor,
|
|
40
|
+
'border-inline-end-color': isCoveredByCurrentColor,
|
|
41
|
+
'border-inline-start-color': isCoveredByCurrentColor,
|
|
42
|
+
'border-left-color': isCoveredByCurrentColor,
|
|
43
|
+
'border-right-color': isCoveredByCurrentColor,
|
|
44
|
+
'border-top-color': isCoveredByCurrentColor,
|
|
45
|
+
'caret-color': isCoveredByCurrentColor,
|
|
46
|
+
'column-rule-color': isCoveredByCurrentColor,
|
|
47
|
+
'outline-color': isCoveredByCurrentColor,
|
|
48
|
+
'text-decoration': (value, property, { currentColor }) => {
|
|
49
|
+
return value === 'none solid currentColor' || value === 'none solid ' + currentColor
|
|
50
|
+
},
|
|
51
|
+
'text-decoration-color': isCoveredByCurrentColor,
|
|
52
|
+
'text-emphasis-color': isCoveredByCurrentColor,
|
|
53
|
+
|
|
54
|
+
// inherited properties:
|
|
55
|
+
'border-collapse': isInherited,
|
|
56
|
+
'border-spacing': isInherited,
|
|
57
|
+
'caption-side': isInherited,
|
|
58
|
+
// N.B. We shouldn't inherit 'color' because there's some UA styling, e.g. `mark` elements
|
|
59
|
+
// 'color': isInherited,
|
|
60
|
+
cursor: isInherited,
|
|
61
|
+
direction: isInherited,
|
|
62
|
+
'empty-cells': isInherited,
|
|
63
|
+
'font-family': isInherited,
|
|
64
|
+
'font-size': isInherited,
|
|
65
|
+
'font-style': isInherited,
|
|
66
|
+
'font-variant': isInherited,
|
|
67
|
+
'font-weight': isInherited,
|
|
68
|
+
'font-size-adjust': isInherited,
|
|
69
|
+
'font-stretch': isInherited,
|
|
70
|
+
font: isInherited,
|
|
71
|
+
'letter-spacing': isInherited,
|
|
72
|
+
'line-height': isInherited,
|
|
73
|
+
'list-style-image': isInherited,
|
|
74
|
+
'list-style-position': isInherited,
|
|
75
|
+
'list-style-type': isInherited,
|
|
76
|
+
'list-style': isInherited,
|
|
77
|
+
orphans: isInherited,
|
|
78
|
+
'overflow-wrap': isInherited,
|
|
79
|
+
quotes: isInherited,
|
|
80
|
+
'stroke-linecap': isInherited,
|
|
81
|
+
'stroke-linejoin': isInherited,
|
|
82
|
+
'tab-size': isInherited,
|
|
83
|
+
'text-align': isInherited,
|
|
84
|
+
'text-align-last': isInherited,
|
|
85
|
+
'text-indent': isInherited,
|
|
86
|
+
'text-justify': isInherited,
|
|
87
|
+
'text-shadow': isInherited,
|
|
88
|
+
'text-transform': isInherited,
|
|
89
|
+
visibility: isInherited,
|
|
90
|
+
'white-space': isInherited,
|
|
91
|
+
'white-space-collapse': isInherited,
|
|
92
|
+
widows: isInherited,
|
|
93
|
+
'word-break': isInherited,
|
|
94
|
+
'word-spacing': isInherited,
|
|
95
|
+
'word-wrap': isInherited,
|
|
96
|
+
|
|
97
|
+
// special border cases - we have a weird case (tailwind seems to trigger this) where all
|
|
98
|
+
// border-styles sometimes get set to 'solid', but the border-width is 0 so they don't render.
|
|
99
|
+
// but in SVGs, **sometimes**, the border-width defaults (i think from a UA style-sheet? but
|
|
100
|
+
// honestly can't tell) to 1.5px so the border displays. we work around this by only including
|
|
101
|
+
// border styles at all if both the border-width and border-style are set to something that
|
|
102
|
+
// would show a border.
|
|
103
|
+
'border-top': isExcludedBorder('top'),
|
|
104
|
+
'border-right': isExcludedBorder('right'),
|
|
105
|
+
'border-bottom': isExcludedBorder('bottom'),
|
|
106
|
+
'border-left': isExcludedBorder('left'),
|
|
107
|
+
'border-block-end': isExcludedBorder('block-end'),
|
|
108
|
+
'border-block-start': isExcludedBorder('block-start'),
|
|
109
|
+
'border-inline-end': isExcludedBorder('inline-end'),
|
|
110
|
+
'border-inline-start': isExcludedBorder('inline-start'),
|
|
111
|
+
'border-top-style': isExcludedBorder('top'),
|
|
112
|
+
'border-right-style': isExcludedBorder('right'),
|
|
113
|
+
'border-bottom-style': isExcludedBorder('bottom'),
|
|
114
|
+
'border-left-style': isExcludedBorder('left'),
|
|
115
|
+
'border-block-end-style': isExcludedBorder('block-end'),
|
|
116
|
+
'border-block-start-style': isExcludedBorder('block-start'),
|
|
117
|
+
'border-inline-end-style': isExcludedBorder('inline-end'),
|
|
118
|
+
'border-inline-start-style': isExcludedBorder('inline-start'),
|
|
119
|
+
'border-top-width': isExcludedBorder('top'),
|
|
120
|
+
'border-right-width': isExcludedBorder('right'),
|
|
121
|
+
'border-bottom-width': isExcludedBorder('bottom'),
|
|
122
|
+
'border-left-width': isExcludedBorder('left'),
|
|
123
|
+
'border-block-end-width': isExcludedBorder('block-end'),
|
|
124
|
+
'border-block-start-width': isExcludedBorder('block-start'),
|
|
125
|
+
'border-inline-end-width': isExcludedBorder('inline-end'),
|
|
126
|
+
} satisfies Record<string, CanSkipRule>
|
|
@@ -110,82 +110,3 @@ export function parseCssValueUrls(value: string) {
|
|
|
110
110
|
url: m[1] || m[2] || m[3],
|
|
111
111
|
}))
|
|
112
112
|
}
|
|
113
|
-
|
|
114
|
-
const currentColorProperties = new Set([
|
|
115
|
-
'border-block-end-color',
|
|
116
|
-
'border-block-start-color',
|
|
117
|
-
'border-bottom-color',
|
|
118
|
-
'border-inline-end-color',
|
|
119
|
-
'border-inline-start-color',
|
|
120
|
-
'border-left-color',
|
|
121
|
-
'border-right-color',
|
|
122
|
-
'border-top-color',
|
|
123
|
-
'caret-color',
|
|
124
|
-
'column-rule-color',
|
|
125
|
-
'outline-color',
|
|
126
|
-
'text-decoration',
|
|
127
|
-
'text-decoration-color',
|
|
128
|
-
'text-emphasis-color',
|
|
129
|
-
])
|
|
130
|
-
|
|
131
|
-
export function isPropertyCoveredByCurrentColor(
|
|
132
|
-
currentColor: string,
|
|
133
|
-
property: string,
|
|
134
|
-
value: string
|
|
135
|
-
) {
|
|
136
|
-
if (currentColorProperties.has(property)) {
|
|
137
|
-
return (
|
|
138
|
-
value === 'currentColor' ||
|
|
139
|
-
value === currentColor ||
|
|
140
|
-
(property === 'text-decoration' && value === `none solid ${currentColor}`)
|
|
141
|
-
)
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const inheritedProperties = new Set([
|
|
146
|
-
'border-collapse',
|
|
147
|
-
'border-spacing',
|
|
148
|
-
'caption-side',
|
|
149
|
-
// N.B. We shouldn't inherit 'color' because there's some UA styling, e.g. `mark` elements
|
|
150
|
-
// 'color',
|
|
151
|
-
'cursor',
|
|
152
|
-
'direction',
|
|
153
|
-
'empty-cells',
|
|
154
|
-
'font-family',
|
|
155
|
-
'font-size',
|
|
156
|
-
'font-style',
|
|
157
|
-
'font-variant',
|
|
158
|
-
'font-weight',
|
|
159
|
-
'font-size-adjust',
|
|
160
|
-
'font-stretch',
|
|
161
|
-
'font',
|
|
162
|
-
'letter-spacing',
|
|
163
|
-
'line-height',
|
|
164
|
-
'list-style-image',
|
|
165
|
-
'list-style-position',
|
|
166
|
-
'list-style-type',
|
|
167
|
-
'list-style',
|
|
168
|
-
'orphans',
|
|
169
|
-
'overflow-wrap',
|
|
170
|
-
'quotes',
|
|
171
|
-
'stroke-linecap',
|
|
172
|
-
'stroke-linejoin',
|
|
173
|
-
'tab-size',
|
|
174
|
-
'text-align',
|
|
175
|
-
'text-align-last',
|
|
176
|
-
'text-indent',
|
|
177
|
-
'text-justify',
|
|
178
|
-
'text-shadow',
|
|
179
|
-
'text-transform',
|
|
180
|
-
'visibility',
|
|
181
|
-
'white-space',
|
|
182
|
-
'white-space-collapse',
|
|
183
|
-
'widows',
|
|
184
|
-
'word-break',
|
|
185
|
-
'word-spacing',
|
|
186
|
-
'word-wrap',
|
|
187
|
-
])
|
|
188
|
-
|
|
189
|
-
export function isPropertyInherited(property: string) {
|
|
190
|
-
return inheritedProperties.has(property)
|
|
191
|
-
}
|
package/src/version.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// This file is automatically generated by internal/scripts/refresh-assets.ts.
|
|
2
2
|
// Do not edit manually. Or do, I'm a comment, not a cop.
|
|
3
3
|
|
|
4
|
-
export const version = '3.12.0-canary.
|
|
4
|
+
export const version = '3.12.0-canary.e333011facbe'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-04-
|
|
8
|
-
patch: '2025-04-
|
|
7
|
+
minor: '2025-04-03T09:52:50.298Z',
|
|
8
|
+
patch: '2025-04-03T09:52:50.298Z',
|
|
9
9
|
}
|