2023-05-30 14:28:56 +00:00
|
|
|
import test, { Page, expect } from '@playwright/test'
|
|
|
|
import { setupPage, setupPageWithShapes } from '../shared-e2e'
|
|
|
|
|
|
|
|
declare const __tldraw_ui_event: { name: string }
|
|
|
|
|
|
|
|
// We're just testing the events, not the actual results.
|
|
|
|
|
|
|
|
let page: Page
|
|
|
|
|
|
|
|
test.describe('Keyboard Shortcuts', () => {
|
|
|
|
test.beforeAll(async ({ browser }) => {
|
|
|
|
page = await browser.newPage()
|
|
|
|
await setupPage(page)
|
|
|
|
})
|
|
|
|
|
2024-01-26 14:49:21 +00:00
|
|
|
test('tools', async ({ isMobile }) => {
|
2023-05-30 14:28:56 +00:00
|
|
|
const geoToolKds = [
|
|
|
|
['r', 'rectangle'],
|
|
|
|
['o', 'ellipse'],
|
|
|
|
]
|
|
|
|
|
|
|
|
for (const [key, geo] of geoToolKds) {
|
|
|
|
await page.keyboard.press('v') // set back to select
|
|
|
|
await page.keyboard.press(key)
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'select-tool',
|
|
|
|
data: { id: `geo-${geo}`, source: 'kbd' },
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
const simpleToolKbds = [
|
|
|
|
['v', 'select'],
|
|
|
|
['h', 'hand'],
|
|
|
|
]
|
|
|
|
|
|
|
|
for (const [key, tool] of simpleToolKbds) {
|
|
|
|
await page.keyboard.press('v') // set back to select
|
|
|
|
await page.keyboard.press(key)
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'select-tool',
|
|
|
|
data: { id: tool, source: 'kbd' },
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
const shapeToolKbds = [
|
|
|
|
['d', 'draw'],
|
|
|
|
['x', 'draw'],
|
|
|
|
['a', 'arrow'],
|
|
|
|
['l', 'line'],
|
|
|
|
['f', 'frame'],
|
|
|
|
['n', 'note'],
|
|
|
|
['f', 'frame'],
|
|
|
|
['e', 'eraser'],
|
|
|
|
['k', 'laser'],
|
|
|
|
['t', 'text'],
|
|
|
|
]
|
|
|
|
|
|
|
|
for (const [key, tool] of shapeToolKbds) {
|
|
|
|
await page.keyboard.press('v') // set back to select
|
|
|
|
await page.keyboard.press(key)
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'select-tool',
|
|
|
|
data: { id: tool, source: 'kbd' },
|
|
|
|
})
|
|
|
|
}
|
2024-01-26 14:49:21 +00:00
|
|
|
|
|
|
|
// make sure that the first dropdown item is rectangle
|
|
|
|
await page.keyboard.press('r')
|
|
|
|
|
|
|
|
const positionalToolKbds = [
|
|
|
|
['1', 'select'],
|
|
|
|
['2', 'hand'],
|
|
|
|
['3', 'draw'],
|
|
|
|
['4', 'eraser'],
|
|
|
|
['5', 'arrow'],
|
|
|
|
['6', 'text'],
|
|
|
|
]
|
|
|
|
|
|
|
|
if (isMobile) {
|
|
|
|
// on mobile, the last item (first from the dropdown) is 7
|
|
|
|
positionalToolKbds.push(['7', 'geo-rectangle'])
|
|
|
|
} else {
|
|
|
|
// on desktop, the last item (first from the dropdown) is 9. 8 is the image tool which
|
|
|
|
// we skip here because it opens a browser dialog
|
|
|
|
positionalToolKbds.push(['9', 'geo-rectangle'])
|
|
|
|
}
|
|
|
|
for (const [key, tool] of positionalToolKbds) {
|
|
|
|
await page.keyboard.press('v') // set back to select
|
|
|
|
await page.keyboard.press(key)
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'select-tool',
|
2024-03-12 16:14:28 +00:00
|
|
|
data: { id: tool, source: 'toolbar' },
|
2024-01-26 14:49:21 +00:00
|
|
|
})
|
|
|
|
}
|
2023-05-30 14:28:56 +00:00
|
|
|
})
|
2023-09-19 15:33:39 +00:00
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
test.describe('Keyboard Shortcuts', () => {
|
|
|
|
test.beforeAll(async ({ browser }) => {
|
|
|
|
page = await browser.newPage()
|
|
|
|
await setupPage(page)
|
|
|
|
|
|
|
|
// Make some shapes
|
|
|
|
await page.keyboard.press('r')
|
|
|
|
await page.mouse.click(100, 100)
|
|
|
|
await page.keyboard.press('r')
|
|
|
|
await page.mouse.click(250, 250)
|
|
|
|
await page.keyboard.press('v')
|
|
|
|
})
|
|
|
|
|
|
|
|
test('Zoom in', async () => {
|
|
|
|
await page.keyboard.press('Control+=')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'zoom-in',
|
|
|
|
data: { source: 'kbd' },
|
2023-05-30 14:28:56 +00:00
|
|
|
})
|
2023-09-19 15:33:39 +00:00
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
test('Zoom out', async () => {
|
|
|
|
await page.keyboard.press('Control+-')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'zoom-out',
|
|
|
|
data: { source: 'kbd' },
|
2023-05-30 14:28:56 +00:00
|
|
|
})
|
2023-09-19 15:33:39 +00:00
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
test('Zoom to fit', async () => {
|
|
|
|
await page.keyboard.press('Shift+1')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'zoom-to-fit',
|
|
|
|
data: { source: 'kbd' },
|
2023-05-30 14:28:56 +00:00
|
|
|
})
|
2023-09-19 15:33:39 +00:00
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
test('Zoom to selection', async () => {
|
|
|
|
await page.keyboard.press('Shift+2')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'zoom-to-selection',
|
|
|
|
data: { source: 'kbd' },
|
2023-05-30 14:28:56 +00:00
|
|
|
})
|
2023-09-19 15:33:39 +00:00
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
test('Zoom to 100', async () => {
|
|
|
|
await page.keyboard.press('Shift+0')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'reset-zoom',
|
|
|
|
data: { source: 'kbd' },
|
2023-05-30 14:28:56 +00:00
|
|
|
})
|
2023-09-19 15:33:39 +00:00
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
/* ---------------------- Files --------------------- */
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// new-project — Cmd+N
|
|
|
|
// open — Cmd+O
|
|
|
|
// save — Cmd+S
|
|
|
|
// save-as — Cmd+Shift+S
|
|
|
|
// upload-media — Cmd+I
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
/* -------------------- Clipboard ------------------- */
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// await page.keyboard.press('Control+c')
|
|
|
|
// expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
// name: 'copy',
|
|
|
|
// data: { source: 'kbd' },
|
|
|
|
// })
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// await page.keyboard.press('Control+v')
|
|
|
|
// expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
// name: 'paste',
|
|
|
|
// data: { source: 'kbd' },
|
|
|
|
// })
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// await page.keyboard.press('Control+x')
|
|
|
|
// expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
// name: 'cut',
|
|
|
|
// data: { source: 'kbd' },
|
|
|
|
// })
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
test('Toggle grid mode', async () => {
|
|
|
|
await page.keyboard.press("Control+'")
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'toggle-grid-mode',
|
|
|
|
data: { source: 'kbd' },
|
2023-05-30 14:28:56 +00:00
|
|
|
})
|
2023-09-19 15:33:39 +00:00
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
test('Toggle dark mode', async () => {
|
|
|
|
await page.keyboard.press('Control+/')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'toggle-dark-mode',
|
|
|
|
data: { source: 'kbd' },
|
2023-05-30 14:28:56 +00:00
|
|
|
})
|
2023-09-19 15:33:39 +00:00
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
test('Toggle tool lock', async () => {
|
|
|
|
await page.keyboard.press('q')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'toggle-tool-lock',
|
|
|
|
data: { source: 'kbd' },
|
2023-05-30 14:28:56 +00:00
|
|
|
})
|
2023-09-19 15:33:39 +00:00
|
|
|
})
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
test.describe('Actions on shapes', () => {
|
|
|
|
test.beforeAll(async ({ browser }) => {
|
|
|
|
page = await browser.newPage()
|
|
|
|
await setupPage(page)
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
/* -------------- Operations on Shapes -------------- */
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
test('Operations on shapes', async () => {
|
|
|
|
await setupPageWithShapes(page)
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2024-03-11 18:31:28 +00:00
|
|
|
// needs shapes on the canvas
|
|
|
|
await page.keyboard.press('Control+Shift+c')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'copy-as',
|
|
|
|
data: { format: 'svg', source: 'kbd' },
|
|
|
|
})
|
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// select-all — Cmd+A
|
|
|
|
await page.keyboard.press('Control+a')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'select-all-shapes',
|
|
|
|
data: { source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// flip-h — Shift+H
|
|
|
|
await page.keyboard.press('Shift+h')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'flip-shapes',
|
|
|
|
data: { operation: 'horizontal', source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// flip-v — Shift+V
|
|
|
|
await page.keyboard.press('Shift+v')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'flip-shapes',
|
|
|
|
data: { operation: 'vertical', source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// move-to-front — ]
|
|
|
|
await page.keyboard.press(']')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'reorder-shapes',
|
|
|
|
data: { operation: 'toFront', source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// move-forward — Alt+]
|
|
|
|
await page.keyboard.press('Alt+]')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'reorder-shapes',
|
|
|
|
data: { operation: 'forward', source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// move-to-back — [
|
|
|
|
await page.keyboard.press('[')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'reorder-shapes',
|
|
|
|
data: { operation: 'toBack', source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// move-backward — Alt+[
|
|
|
|
await page.keyboard.press('Alt+[')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'reorder-shapes',
|
|
|
|
data: { operation: 'backward', source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// group — Cmd+G
|
|
|
|
await page.keyboard.press('Control+g')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'group-shapes',
|
|
|
|
data: { source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// ungroup — Cmd+Shift+G
|
|
|
|
await page.keyboard.press('Control+Shift+g')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'ungroup-shapes',
|
|
|
|
data: { source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// duplicate — Cmd+D
|
|
|
|
await page.keyboard.press('Control+d')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'duplicate-shapes',
|
|
|
|
data: { source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// align left — Alt+A
|
|
|
|
await page.keyboard.press('Alt+a')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'align-shapes',
|
|
|
|
data: { operation: 'left', source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// align right — Alt+D
|
|
|
|
await page.keyboard.press('Alt+d')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'align-shapes',
|
|
|
|
data: { operation: 'right', source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// align top — Alt+W
|
|
|
|
await page.keyboard.press('Alt+w')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'align-shapes',
|
|
|
|
data: { operation: 'top', source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// align bottom — Alt+W'
|
|
|
|
await page.keyboard.press('Alt+s')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'align-shapes',
|
|
|
|
data: { operation: 'bottom', source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// delete — backspace
|
|
|
|
await page.keyboard.press('Control+a') // selected
|
|
|
|
await page.keyboard.press('Backspace')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'delete-shapes',
|
|
|
|
data: { source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// delete — ⌫
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// Make some shapes and select them
|
|
|
|
await page.keyboard.press('r')
|
|
|
|
await page.mouse.click(100, 100)
|
|
|
|
await page.keyboard.press('r')
|
|
|
|
await page.mouse.click(250, 250)
|
|
|
|
await page.keyboard.press('v')
|
|
|
|
await page.keyboard.press('Control+a')
|
2023-06-29 21:43:28 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
await page.keyboard.press('Delete')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'delete-shapes',
|
|
|
|
data: { source: 'kbd' },
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
/* ---------------------- Misc ---------------------- */
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// toggle lock
|
|
|
|
await page.keyboard.press('Shift+l')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'toggle-lock',
|
|
|
|
})
|
2023-05-30 14:28:56 +00:00
|
|
|
|
2023-09-19 15:33:39 +00:00
|
|
|
// await page.keyboard.press('Control+i')
|
|
|
|
// expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
// name: 'open-menu',
|
|
|
|
// data: { source: 'dialog' },
|
|
|
|
// })
|
|
|
|
|
|
|
|
// await page.keyboard.press('Control+u')
|
|
|
|
// expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
// name: 'open-menu',
|
|
|
|
// data: { source: 'dialog' },
|
|
|
|
// })
|
2023-05-30 14:28:56 +00:00
|
|
|
})
|
|
|
|
})
|
tldraw zero - package shuffle (#1710)
This PR moves code between our packages so that:
- @tldraw/editor is a “core” library with the engine and canvas but no
shapes, tools, or other things
- @tldraw/tldraw contains everything particular to the experience we’ve
built for tldraw
At first look, this might seem like a step away from customization and
configuration, however I believe it greatly increases the configuration
potential of the @tldraw/editor while also providing a more accurate
reflection of what configuration options actually exist for
@tldraw/tldraw.
## Library changes
@tldraw/editor re-exports its dependencies and @tldraw/tldraw re-exports
@tldraw/editor.
- users of @tldraw/editor WITHOUT @tldraw/tldraw should almost always
only import things from @tldraw/editor.
- users of @tldraw/tldraw should almost always only import things from
@tldraw/tldraw.
- @tldraw/polyfills is merged into @tldraw/editor
- @tldraw/indices is merged into @tldraw/editor
- @tldraw/primitives is merged mostly into @tldraw/editor, partially
into @tldraw/tldraw
- @tldraw/file-format is merged into @tldraw/tldraw
- @tldraw/ui is merged into @tldraw/tldraw
Many (many) utils and other code is moved from the editor to tldraw. For
example, embeds now are entirely an feature of @tldraw/tldraw. The only
big chunk of code left in core is related to arrow handling.
## API Changes
The editor can now be used without tldraw's assets. We load them in
@tldraw/tldraw instead, so feel free to use whatever fonts or images or
whatever that you like with the editor.
All tools and shapes (except for the `Group` shape) are moved to
@tldraw/tldraw. This includes the `select` tool.
You should use the editor with at least one tool, however, so you now
also need to send in an `initialState` prop to the Editor /
<TldrawEditor> component indicating which state the editor should begin
in.
The `components` prop now also accepts `SelectionForeground`.
The complex selection component that we use for tldraw is moved to
@tldraw/tldraw. The default component is quite basic but can easily be
replaced via the `components` prop. We pass down our tldraw-flavored
SelectionFg via `components`.
Likewise with the `Scribble` component: the `DefaultScribble` no longer
uses our freehand tech and is a simple path instead. We pass down the
tldraw-flavored scribble via `components`.
The `ExternalContentManager` (`Editor.externalContentManager`) is
removed and replaced with a mapping of types to handlers.
- Register new content handlers with
`Editor.registerExternalContentHandler`.
- Register new asset creation handlers (for files and URLs) with
`Editor.registerExternalAssetHandler`
### Change Type
- [x] `major` — Breaking change
### Test Plan
- [x] Unit Tests
- [x] End to end tests
### Release Notes
- [@tldraw/editor] lots, wip
- [@tldraw/ui] gone, merged to tldraw/tldraw
- [@tldraw/polyfills] gone, merged to tldraw/editor
- [@tldraw/primitives] gone, merged to tldraw/editor / tldraw/tldraw
- [@tldraw/indices] gone, merged to tldraw/editor
- [@tldraw/file-format] gone, merged to tldraw/tldraw
---------
Co-authored-by: alex <alex@dytry.ch>
2023-07-17 21:22:34 +00:00
|
|
|
|
|
|
|
test.describe('Delete bug', () => {
|
2023-07-18 22:13:11 +00:00
|
|
|
test.beforeEach(async ({ browser }) => {
|
tldraw zero - package shuffle (#1710)
This PR moves code between our packages so that:
- @tldraw/editor is a “core” library with the engine and canvas but no
shapes, tools, or other things
- @tldraw/tldraw contains everything particular to the experience we’ve
built for tldraw
At first look, this might seem like a step away from customization and
configuration, however I believe it greatly increases the configuration
potential of the @tldraw/editor while also providing a more accurate
reflection of what configuration options actually exist for
@tldraw/tldraw.
## Library changes
@tldraw/editor re-exports its dependencies and @tldraw/tldraw re-exports
@tldraw/editor.
- users of @tldraw/editor WITHOUT @tldraw/tldraw should almost always
only import things from @tldraw/editor.
- users of @tldraw/tldraw should almost always only import things from
@tldraw/tldraw.
- @tldraw/polyfills is merged into @tldraw/editor
- @tldraw/indices is merged into @tldraw/editor
- @tldraw/primitives is merged mostly into @tldraw/editor, partially
into @tldraw/tldraw
- @tldraw/file-format is merged into @tldraw/tldraw
- @tldraw/ui is merged into @tldraw/tldraw
Many (many) utils and other code is moved from the editor to tldraw. For
example, embeds now are entirely an feature of @tldraw/tldraw. The only
big chunk of code left in core is related to arrow handling.
## API Changes
The editor can now be used without tldraw's assets. We load them in
@tldraw/tldraw instead, so feel free to use whatever fonts or images or
whatever that you like with the editor.
All tools and shapes (except for the `Group` shape) are moved to
@tldraw/tldraw. This includes the `select` tool.
You should use the editor with at least one tool, however, so you now
also need to send in an `initialState` prop to the Editor /
<TldrawEditor> component indicating which state the editor should begin
in.
The `components` prop now also accepts `SelectionForeground`.
The complex selection component that we use for tldraw is moved to
@tldraw/tldraw. The default component is quite basic but can easily be
replaced via the `components` prop. We pass down our tldraw-flavored
SelectionFg via `components`.
Likewise with the `Scribble` component: the `DefaultScribble` no longer
uses our freehand tech and is a simple path instead. We pass down the
tldraw-flavored scribble via `components`.
The `ExternalContentManager` (`Editor.externalContentManager`) is
removed and replaced with a mapping of types to handlers.
- Register new content handlers with
`Editor.registerExternalContentHandler`.
- Register new asset creation handlers (for files and URLs) with
`Editor.registerExternalAssetHandler`
### Change Type
- [x] `major` — Breaking change
### Test Plan
- [x] Unit Tests
- [x] End to end tests
### Release Notes
- [@tldraw/editor] lots, wip
- [@tldraw/ui] gone, merged to tldraw/tldraw
- [@tldraw/polyfills] gone, merged to tldraw/editor
- [@tldraw/primitives] gone, merged to tldraw/editor / tldraw/tldraw
- [@tldraw/indices] gone, merged to tldraw/editor
- [@tldraw/file-format] gone, merged to tldraw/tldraw
---------
Co-authored-by: alex <alex@dytry.ch>
2023-07-17 21:22:34 +00:00
|
|
|
page = await browser.newPage()
|
|
|
|
await setupPage(page)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('delete bug without drag', async () => {
|
|
|
|
await page.keyboard.press('r')
|
|
|
|
await page.mouse.click(100, 100)
|
|
|
|
await page.keyboard.press('Backspace')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'delete-shapes',
|
|
|
|
data: { source: 'kbd' },
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
test('delete bug with drag', async () => {
|
|
|
|
await page.keyboard.press('r')
|
|
|
|
await page.mouse.down()
|
2023-07-18 22:13:11 +00:00
|
|
|
await page.mouse.move(100, 100)
|
tldraw zero - package shuffle (#1710)
This PR moves code between our packages so that:
- @tldraw/editor is a “core” library with the engine and canvas but no
shapes, tools, or other things
- @tldraw/tldraw contains everything particular to the experience we’ve
built for tldraw
At first look, this might seem like a step away from customization and
configuration, however I believe it greatly increases the configuration
potential of the @tldraw/editor while also providing a more accurate
reflection of what configuration options actually exist for
@tldraw/tldraw.
## Library changes
@tldraw/editor re-exports its dependencies and @tldraw/tldraw re-exports
@tldraw/editor.
- users of @tldraw/editor WITHOUT @tldraw/tldraw should almost always
only import things from @tldraw/editor.
- users of @tldraw/tldraw should almost always only import things from
@tldraw/tldraw.
- @tldraw/polyfills is merged into @tldraw/editor
- @tldraw/indices is merged into @tldraw/editor
- @tldraw/primitives is merged mostly into @tldraw/editor, partially
into @tldraw/tldraw
- @tldraw/file-format is merged into @tldraw/tldraw
- @tldraw/ui is merged into @tldraw/tldraw
Many (many) utils and other code is moved from the editor to tldraw. For
example, embeds now are entirely an feature of @tldraw/tldraw. The only
big chunk of code left in core is related to arrow handling.
## API Changes
The editor can now be used without tldraw's assets. We load them in
@tldraw/tldraw instead, so feel free to use whatever fonts or images or
whatever that you like with the editor.
All tools and shapes (except for the `Group` shape) are moved to
@tldraw/tldraw. This includes the `select` tool.
You should use the editor with at least one tool, however, so you now
also need to send in an `initialState` prop to the Editor /
<TldrawEditor> component indicating which state the editor should begin
in.
The `components` prop now also accepts `SelectionForeground`.
The complex selection component that we use for tldraw is moved to
@tldraw/tldraw. The default component is quite basic but can easily be
replaced via the `components` prop. We pass down our tldraw-flavored
SelectionFg via `components`.
Likewise with the `Scribble` component: the `DefaultScribble` no longer
uses our freehand tech and is a simple path instead. We pass down the
tldraw-flavored scribble via `components`.
The `ExternalContentManager` (`Editor.externalContentManager`) is
removed and replaced with a mapping of types to handlers.
- Register new content handlers with
`Editor.registerExternalContentHandler`.
- Register new asset creation handlers (for files and URLs) with
`Editor.registerExternalAssetHandler`
### Change Type
- [x] `major` — Breaking change
### Test Plan
- [x] Unit Tests
- [x] End to end tests
### Release Notes
- [@tldraw/editor] lots, wip
- [@tldraw/ui] gone, merged to tldraw/tldraw
- [@tldraw/polyfills] gone, merged to tldraw/editor
- [@tldraw/primitives] gone, merged to tldraw/editor / tldraw/tldraw
- [@tldraw/indices] gone, merged to tldraw/editor
- [@tldraw/file-format] gone, merged to tldraw/tldraw
---------
Co-authored-by: alex <alex@dytry.ch>
2023-07-17 21:22:34 +00:00
|
|
|
await page.mouse.up()
|
|
|
|
await page.keyboard.press('Backspace')
|
|
|
|
expect(await page.evaluate(() => __tldraw_ui_event)).toMatchObject({
|
|
|
|
name: 'delete-shapes',
|
|
|
|
data: { source: 'kbd' },
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|