tldraw 4.2.0-canary.e6ed9aee7fe4 → 4.2.0-canary.e7800b04c779
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 +2 -1
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +5 -2
- package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +63 -36
- package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js.map +2 -2
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/ShapeFill.js +3 -0
- package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
- package/dist-cjs/lib/ui/components/Dialogs.js +2 -14
- package/dist-cjs/lib/ui/components/Dialogs.js.map +2 -2
- package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +5 -4
- package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultRichTextToolbarContent.js +2 -1
- package/dist-cjs/lib/ui/components/Toolbar/DefaultRichTextToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButton.js +2 -2
- package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButton.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +2 -1
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +16 -0
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +1 -0
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTranslation/useTranslation.js +1 -0
- package/dist-cjs/lib/ui/hooks/useTranslation/useTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-esm/index.d.mts +2 -1
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs +6 -2
- package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs +65 -38
- package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -5
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs +3 -0
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Dialogs.mjs +2 -14
- package/dist-esm/lib/ui/components/Dialogs.mjs.map +2 -2
- package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +5 -5
- package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultRichTextToolbarContent.mjs +2 -1
- package/dist-esm/lib/ui/components/Toolbar/DefaultRichTextToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/Button/TldrawUiButton.mjs +2 -2
- package/dist-esm/lib/ui/components/primitives/Button/TldrawUiButton.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +2 -1
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +16 -0
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +1 -0
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/useTranslation.mjs +1 -0
- package/dist-esm/lib/ui/hooks/useTranslation/useTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/package.json +3 -3
- package/src/lib/canvas/TldrawSelectionForeground.tsx +18 -2
- package/src/lib/shapes/frame/components/FrameLabelInput.tsx +48 -24
- package/src/lib/shapes/note/NoteShapeUtil.tsx +6 -5
- package/src/lib/shapes/shared/ShapeFill.tsx +3 -0
- package/src/lib/ui/components/Dialogs.tsx +2 -14
- package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +6 -5
- package/src/lib/ui/components/Toolbar/DefaultRichTextToolbarContent.tsx +4 -1
- package/src/lib/ui/components/primitives/Button/TldrawUiButton.tsx +3 -2
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +1 -0
- package/src/lib/ui/context/actions.tsx +16 -0
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +1 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +1 -0
- package/src/lib/ui/hooks/useTranslation/useTranslation.tsx +2 -1
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +4 -6
- package/src/test/TldrawEditor.test.tsx +74 -29
- package/tldraw.css +4 -6
|
@@ -1495,6 +1495,22 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
|
|
1495
1495
|
trackEvent('set-style', { source, id: style.id, value: 'fill' })
|
|
1496
1496
|
},
|
|
1497
1497
|
},
|
|
1498
|
+
{
|
|
1499
|
+
id: 'select-fill-lined-fill',
|
|
1500
|
+
label: 'fill-style.lined-fill',
|
|
1501
|
+
kbd: 'alt+shift+f',
|
|
1502
|
+
onSelect(source) {
|
|
1503
|
+
const style = DefaultFillStyle
|
|
1504
|
+
editor.run(() => {
|
|
1505
|
+
editor.markHistoryStoppingPoint('change-fill')
|
|
1506
|
+
if (editor.isIn('select')) {
|
|
1507
|
+
editor.setStyleForSelectedShapes(style, 'lined-fill')
|
|
1508
|
+
}
|
|
1509
|
+
editor.setStyleForNextShapes(style, 'lined-fill')
|
|
1510
|
+
})
|
|
1511
|
+
trackEvent('set-style', { source, id: style.id, value: 'lined-fill' })
|
|
1512
|
+
},
|
|
1513
|
+
},
|
|
1498
1514
|
{
|
|
1499
1515
|
id: 'flatten-to-image',
|
|
1500
1516
|
label: 'action.flatten-to-image',
|
|
@@ -155,6 +155,7 @@ export const DEFAULT_TRANSLATION = {
|
|
|
155
155
|
'fill-style.solid': 'Solid',
|
|
156
156
|
'fill-style.pattern': 'Pattern',
|
|
157
157
|
'fill-style.fill': 'Fill',
|
|
158
|
+
'fill-style.lined-fill': 'Lined fill',
|
|
158
159
|
'dash-style.dashed': 'Dashed',
|
|
159
160
|
'dash-style.dotted': 'Dotted',
|
|
160
161
|
'dash-style.draw': 'Draw',
|
|
@@ -23,7 +23,8 @@ export interface TLUiTranslationProviderProps {
|
|
|
23
23
|
/** @public */
|
|
24
24
|
export type TLUiTranslationContextType = TLUiTranslation
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
/** @internal */
|
|
27
|
+
export const TranslationsContext = React.createContext<TLUiTranslationContextType | null>(null)
|
|
27
28
|
|
|
28
29
|
/** @public */
|
|
29
30
|
export function useCurrentTranslation() {
|
package/src/lib/ui/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 = '4.2.0-canary.
|
|
4
|
+
export const version = '4.2.0-canary.e7800b04c779'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2025-09-18T14:39:22.803Z',
|
|
7
|
-
minor: '2025-
|
|
8
|
-
patch: '2025-
|
|
7
|
+
minor: '2025-11-14T14:34:54.102Z',
|
|
8
|
+
patch: '2025-11-14T14:34:54.102Z',
|
|
9
9
|
}
|
package/src/lib/ui.css
CHANGED
|
@@ -514,12 +514,10 @@
|
|
|
514
514
|
/* If mobile use 16px as font size */
|
|
515
515
|
/* On iOS, font size under 16px in an input will make the page zoom into the input 🤦♂️ */
|
|
516
516
|
/* https://css-tricks.com/16px-or-larger-text-prevents-ios-form-zoom/ */
|
|
517
|
-
@
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
font-size: 16px;
|
|
522
|
-
}
|
|
517
|
+
@supports (-webkit-touch-callout: none) {
|
|
518
|
+
/* CSS specific to iOS devices */
|
|
519
|
+
.tlui-input {
|
|
520
|
+
font-size: 16px;
|
|
523
521
|
}
|
|
524
522
|
}
|
|
525
523
|
|
|
@@ -6,16 +6,17 @@ import {
|
|
|
6
6
|
HTMLContainer,
|
|
7
7
|
TLAssetStore,
|
|
8
8
|
TLBaseShape,
|
|
9
|
+
TLShapeId,
|
|
9
10
|
TldrawEditor,
|
|
10
11
|
createShapeId,
|
|
11
12
|
createTLStore,
|
|
12
13
|
noop,
|
|
14
|
+
toRichText,
|
|
13
15
|
} from '@tldraw/editor'
|
|
14
16
|
import { StrictMode } from 'react'
|
|
15
17
|
import { vi } from 'vitest'
|
|
16
18
|
import { defaultShapeUtils } from '../lib/defaultShapeUtils'
|
|
17
19
|
import { defaultTools } from '../lib/defaultTools'
|
|
18
|
-
import { GeoShapeUtil } from '../lib/shapes/geo/GeoShapeUtil'
|
|
19
20
|
import { defaultAddFontsFromNode, tipTapDefaultExtensions } from '../lib/utils/text/richText'
|
|
20
21
|
import {
|
|
21
22
|
renderTldrawComponent,
|
|
@@ -169,7 +170,7 @@ describe('<TldrawEditor />', () => {
|
|
|
169
170
|
let editor = {} as Editor
|
|
170
171
|
await renderTldrawComponent(
|
|
171
172
|
<TldrawEditor
|
|
172
|
-
shapeUtils={
|
|
173
|
+
shapeUtils={defaultShapeUtils}
|
|
173
174
|
initialState="select"
|
|
174
175
|
tools={defaultTools}
|
|
175
176
|
onMount={(editorApp) => {
|
|
@@ -185,39 +186,83 @@ describe('<TldrawEditor />', () => {
|
|
|
185
186
|
editor.updateInstanceState({ screenBounds: { x: 0, y: 0, w: 1080, h: 720 } })
|
|
186
187
|
})
|
|
187
188
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
189
|
+
// Test all shape types except group
|
|
190
|
+
const shapeTypesToTest = [
|
|
191
|
+
{ type: 'arrow' as const, props: { start: { x: 0, y: 0 }, end: { x: 100, y: 100 } } },
|
|
192
|
+
{ type: 'bookmark' as const, props: { w: 100, h: 100, url: 'https://example.com' } },
|
|
193
|
+
{
|
|
194
|
+
type: 'draw' as const,
|
|
195
|
+
props: { segments: [{ type: 'free' as const, points: [{ x: 0, y: 0, z: 0.5 }] }] },
|
|
196
|
+
},
|
|
197
|
+
{ type: 'embed' as const, props: { w: 100, h: 100, url: 'https://example.com' } },
|
|
198
|
+
{ type: 'frame' as const, props: { w: 100, h: 100 } },
|
|
199
|
+
{ type: 'geo' as const, props: { w: 100, h: 100, geo: 'rectangle' } },
|
|
200
|
+
{
|
|
201
|
+
type: 'highlight' as const,
|
|
202
|
+
props: { segments: [{ type: 'free' as const, points: [{ x: 0, y: 0, z: 0.5 }] }] },
|
|
203
|
+
},
|
|
204
|
+
{ type: 'image' as const, props: { w: 100, h: 100 } },
|
|
205
|
+
{
|
|
206
|
+
type: 'line' as const,
|
|
207
|
+
props: {
|
|
208
|
+
points: {
|
|
209
|
+
a1: { id: 'a1', index: 'a1', x: 0, y: 0 },
|
|
210
|
+
a2: { id: 'a2', index: 'a2', x: 100, y: 100 },
|
|
211
|
+
},
|
|
196
212
|
},
|
|
197
|
-
|
|
198
|
-
|
|
213
|
+
},
|
|
214
|
+
{ type: 'note' as const, props: { richText: toRichText('test') } },
|
|
215
|
+
{ type: 'text' as const, props: { w: 100, richText: toRichText('test') } },
|
|
216
|
+
{ type: 'video' as const, props: { w: 100, h: 100 } },
|
|
217
|
+
]
|
|
218
|
+
|
|
219
|
+
const shapeIds: TLShapeId[] = []
|
|
220
|
+
|
|
221
|
+
for (let i = 0; i < shapeTypesToTest.length; i++) {
|
|
222
|
+
const shapeConfig = shapeTypesToTest[i]
|
|
223
|
+
const id = createShapeId()
|
|
224
|
+
shapeIds.push(id)
|
|
225
|
+
|
|
226
|
+
await act(async () => {
|
|
227
|
+
editor.createShapes([
|
|
228
|
+
{
|
|
229
|
+
id,
|
|
230
|
+
type: shapeConfig.type,
|
|
231
|
+
x: i * 150, // Space them out horizontally
|
|
232
|
+
y: 0,
|
|
233
|
+
props: shapeConfig.props,
|
|
234
|
+
},
|
|
235
|
+
])
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
// Does the shape exist?
|
|
239
|
+
const shape = editor.getShape(id)
|
|
240
|
+
expect(shape).toBeTruthy()
|
|
241
|
+
expect(shape?.type).toBe(shapeConfig.type)
|
|
242
|
+
|
|
243
|
+
// Check that all shapes rendered without error boundaries
|
|
244
|
+
expect(
|
|
245
|
+
document.querySelectorAll('.tl-shape-error-boundary'),
|
|
246
|
+
`${shapeConfig.type} had an error while rendering`
|
|
247
|
+
).toHaveLength(0)
|
|
248
|
+
}
|
|
199
249
|
|
|
200
|
-
//
|
|
201
|
-
expect(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
x: 0,
|
|
205
|
-
y: 0,
|
|
206
|
-
opacity: 1,
|
|
207
|
-
props: { geo: 'rectangle', w: 100, h: 100 },
|
|
208
|
-
})
|
|
250
|
+
// Check that all shape components are rendering
|
|
251
|
+
expect(document.querySelectorAll('.tl-shape').length).toBeGreaterThanOrEqual(
|
|
252
|
+
shapeTypesToTest.length
|
|
253
|
+
)
|
|
209
254
|
|
|
210
|
-
//
|
|
211
|
-
expect(document.querySelectorAll('.tl-shape')).
|
|
212
|
-
|
|
213
|
-
|
|
255
|
+
// Check that all shape indicators are present
|
|
256
|
+
expect(document.querySelectorAll('.tl-shape-indicator').length).toBeGreaterThanOrEqual(
|
|
257
|
+
shapeTypesToTest.length
|
|
258
|
+
)
|
|
214
259
|
|
|
215
|
-
// Select the shape
|
|
216
|
-
|
|
260
|
+
// Select one of the shapes (the note shape)
|
|
261
|
+
const noteShapeId = shapeIds[9] // note is at index 9
|
|
262
|
+
await act(async () => editor.select(noteShapeId))
|
|
217
263
|
|
|
218
264
|
expect(editor.getSelectedShapeIds().length).toBe(1)
|
|
219
|
-
|
|
220
|
-
expect(document.querySelectorAll('.tl-shape-indicator')).toHaveLength(1)
|
|
265
|
+
expect(editor.getSelectedShapeIds()[0]).toBe(noteShapeId)
|
|
221
266
|
|
|
222
267
|
// Select the eraser tool...
|
|
223
268
|
await act(async () => editor.setCurrentTool('eraser'))
|
package/tldraw.css
CHANGED
|
@@ -2315,12 +2315,10 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
2315
2315
|
/* If mobile use 16px as font size */
|
|
2316
2316
|
/* On iOS, font size under 16px in an input will make the page zoom into the input 🤦♂️ */
|
|
2317
2317
|
/* https://css-tricks.com/16px-or-larger-text-prevents-ios-form-zoom/ */
|
|
2318
|
-
@
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
font-size: 16px;
|
|
2323
|
-
}
|
|
2318
|
+
@supports (-webkit-touch-callout: none) {
|
|
2319
|
+
/* CSS specific to iOS devices */
|
|
2320
|
+
.tlui-input {
|
|
2321
|
+
font-size: 16px;
|
|
2324
2322
|
}
|
|
2325
2323
|
}
|
|
2326
2324
|
|