tldraw 4.4.0-canary.afdcafe834b3 → 4.4.0-canary.bb78e813fee7
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 +112 -1
- package/dist-cjs/index.js +10 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js +6 -1
- package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSelect.js +144 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSelect.js.map +7 -0
- 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 +112 -1
- package/dist-esm/index.mjs +17 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs +6 -1
- package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSelect.mjs +114 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiSelect.mjs.map +7 -0
- 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/index.ts +15 -1
- package/src/lib/bindings/arrow/ArrowBindingUtil.ts +12 -0
- package/src/lib/ui/components/primitives/TldrawUiSelect.tsx +211 -0
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +46 -0
- package/tldraw.css +46 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useContainer } from "@tldraw/editor";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import { Select as _Select } from "radix-ui";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { useMenuIsOpen } from "../../hooks/useMenuIsOpen.mjs";
|
|
7
|
+
import { TldrawUiIcon } from "./TldrawUiIcon.mjs";
|
|
8
|
+
function TldrawUiSelect({
|
|
9
|
+
id,
|
|
10
|
+
value,
|
|
11
|
+
onValueChange,
|
|
12
|
+
onOpenChange,
|
|
13
|
+
disabled,
|
|
14
|
+
className,
|
|
15
|
+
children,
|
|
16
|
+
"data-testid": dataTestId,
|
|
17
|
+
"aria-label": ariaLabel
|
|
18
|
+
}) {
|
|
19
|
+
const [open, handleOpenChange] = useMenuIsOpen(id, onOpenChange);
|
|
20
|
+
return /* @__PURE__ */ jsx(
|
|
21
|
+
_Select.Root,
|
|
22
|
+
{
|
|
23
|
+
value,
|
|
24
|
+
onValueChange,
|
|
25
|
+
onOpenChange: handleOpenChange,
|
|
26
|
+
open,
|
|
27
|
+
disabled,
|
|
28
|
+
dir: "ltr",
|
|
29
|
+
children: /* @__PURE__ */ jsx(
|
|
30
|
+
"div",
|
|
31
|
+
{
|
|
32
|
+
id,
|
|
33
|
+
className: classNames("tlui-select", className),
|
|
34
|
+
"data-testid": dataTestId,
|
|
35
|
+
"aria-label": ariaLabel,
|
|
36
|
+
children
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
const TldrawUiSelectTrigger = React.forwardRef(
|
|
43
|
+
function TldrawUiSelectTrigger2({ children, className }, ref) {
|
|
44
|
+
return /* @__PURE__ */ jsxs(
|
|
45
|
+
_Select.Trigger,
|
|
46
|
+
{
|
|
47
|
+
ref,
|
|
48
|
+
className: classNames("tlui-button tlui-select__trigger", className),
|
|
49
|
+
children: [
|
|
50
|
+
children,
|
|
51
|
+
/* @__PURE__ */ jsx(_Select.Icon, { className: "tlui-select__chevron", children: /* @__PURE__ */ jsx(TldrawUiIcon, { icon: "chevron-down", label: "", small: true }) })
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
function TldrawUiSelectValue({ placeholder, icon, children }) {
|
|
58
|
+
return /* @__PURE__ */ jsx(_Select.Value, { placeholder, children: /* @__PURE__ */ jsxs("span", { className: "tlui-select__value", children: [
|
|
59
|
+
icon && /* @__PURE__ */ jsx(TldrawUiIcon, { icon, label: "", small: true }),
|
|
60
|
+
/* @__PURE__ */ jsx("span", { className: "tlui-button__label", children })
|
|
61
|
+
] }) });
|
|
62
|
+
}
|
|
63
|
+
function TldrawUiSelectContent({
|
|
64
|
+
children,
|
|
65
|
+
side = "bottom",
|
|
66
|
+
align = "start",
|
|
67
|
+
className
|
|
68
|
+
}) {
|
|
69
|
+
const container = useContainer();
|
|
70
|
+
return /* @__PURE__ */ jsx(_Select.Portal, { container, children: /* @__PURE__ */ jsx(
|
|
71
|
+
_Select.Content,
|
|
72
|
+
{
|
|
73
|
+
className: classNames("tlui-menu tlui-select__content", className),
|
|
74
|
+
position: "popper",
|
|
75
|
+
side,
|
|
76
|
+
align,
|
|
77
|
+
sideOffset: 4,
|
|
78
|
+
collisionPadding: 4,
|
|
79
|
+
children: /* @__PURE__ */ jsx(_Select.Viewport, { className: "tlui-select__viewport", children })
|
|
80
|
+
}
|
|
81
|
+
) });
|
|
82
|
+
}
|
|
83
|
+
function TldrawUiSelectItem({
|
|
84
|
+
value,
|
|
85
|
+
label,
|
|
86
|
+
icon,
|
|
87
|
+
disabled,
|
|
88
|
+
className
|
|
89
|
+
}) {
|
|
90
|
+
return /* @__PURE__ */ jsxs(
|
|
91
|
+
_Select.Item,
|
|
92
|
+
{
|
|
93
|
+
value,
|
|
94
|
+
disabled,
|
|
95
|
+
className: classNames(
|
|
96
|
+
"tlui-button tlui-button__menu tlui-button__checkbox tlui-select__item",
|
|
97
|
+
className
|
|
98
|
+
),
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ jsx(TldrawUiIcon, { small: true, icon: "check", label: "", className: "tlui-select__item-indicator" }),
|
|
101
|
+
icon && /* @__PURE__ */ jsx(TldrawUiIcon, { icon, label: "", small: true }),
|
|
102
|
+
/* @__PURE__ */ jsx(_Select.ItemText, { className: "tlui-button__label", children: label })
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
TldrawUiSelect,
|
|
109
|
+
TldrawUiSelectContent,
|
|
110
|
+
TldrawUiSelectItem,
|
|
111
|
+
TldrawUiSelectTrigger,
|
|
112
|
+
TldrawUiSelectValue
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=TldrawUiSelect.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/lib/ui/components/primitives/TldrawUiSelect.tsx"],
|
|
4
|
+
"sourcesContent": ["import { useContainer } from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { Select as _Select } from 'radix-ui'\nimport * as React from 'react'\nimport { useMenuIsOpen } from '../../hooks/useMenuIsOpen'\nimport { TLUiIconType } from '../../icon-types'\nimport { TldrawUiIcon } from './TldrawUiIcon'\n\n/* --------------------- Root --------------------- */\n\n/** @public */\nexport interface TLUiSelectProps {\n\tid: string\n\tvalue: string\n\tonValueChange(value: string): void\n\tonOpenChange?(isOpen: boolean): void\n\tdisabled?: boolean\n\tclassName?: string\n\tchildren: React.ReactNode\n\t'data-testid'?: string\n\t'aria-label'?: string\n}\n\n/**\n * A select dropdown component.\n *\n * @example\n * ```tsx\n * <TldrawUiSelect id=\"my-select\" value={value} onValueChange={setValue}>\n * <TldrawUiSelectTrigger>\n * <TldrawUiSelectValue placeholder=\"Select...\" />\n * </TldrawUiSelectTrigger>\n * <TldrawUiSelectContent>\n * <TldrawUiSelectItem value=\"one\" label=\"One\" />\n * <TldrawUiSelectItem value=\"two\" label=\"Two\" />\n * </TldrawUiSelectContent>\n * </TldrawUiSelect>\n * ```\n *\n * @public\n * @react\n */\nexport function TldrawUiSelect({\n\tid,\n\tvalue,\n\tonValueChange,\n\tonOpenChange,\n\tdisabled,\n\tclassName,\n\tchildren,\n\t'data-testid': dataTestId,\n\t'aria-label': ariaLabel,\n}: TLUiSelectProps) {\n\tconst [open, handleOpenChange] = useMenuIsOpen(id, onOpenChange)\n\n\treturn (\n\t\t<_Select.Root\n\t\t\tvalue={value}\n\t\t\tonValueChange={onValueChange}\n\t\t\tonOpenChange={handleOpenChange}\n\t\t\topen={open}\n\t\t\tdisabled={disabled}\n\t\t\tdir=\"ltr\"\n\t\t>\n\t\t\t<div\n\t\t\t\tid={id}\n\t\t\t\tclassName={classNames('tlui-select', className)}\n\t\t\t\tdata-testid={dataTestId}\n\t\t\t\taria-label={ariaLabel}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</_Select.Root>\n\t)\n}\n\n/* --------------------- Trigger --------------------- */\n\n/** @public */\nexport interface TLUiSelectTriggerProps {\n\tchildren: React.ReactNode\n\tclassName?: string\n}\n\n/**\n * The trigger button for the select dropdown.\n *\n * @public\n * @react\n */\nexport const TldrawUiSelectTrigger = React.forwardRef<HTMLButtonElement, TLUiSelectTriggerProps>(\n\tfunction TldrawUiSelectTrigger({ children, className }, ref) {\n\t\treturn (\n\t\t\t<_Select.Trigger\n\t\t\t\tref={ref}\n\t\t\t\tclassName={classNames('tlui-button tlui-select__trigger', className)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t<_Select.Icon className=\"tlui-select__chevron\">\n\t\t\t\t\t<TldrawUiIcon icon=\"chevron-down\" label=\"\" small />\n\t\t\t\t</_Select.Icon>\n\t\t\t</_Select.Trigger>\n\t\t)\n\t}\n)\n\n/* --------------------- Value --------------------- */\n\n/** @public */\nexport interface TLUiSelectValueProps {\n\tplaceholder?: string\n\ticon?: TLUiIconType | Exclude<string, TLUiIconType>\n\tchildren?: React.ReactNode\n}\n\n/**\n * Displays the currently selected value in the trigger.\n *\n * @public\n * @react\n */\nexport function TldrawUiSelectValue({ placeholder, icon, children }: TLUiSelectValueProps) {\n\treturn (\n\t\t<_Select.Value placeholder={placeholder}>\n\t\t\t<span className=\"tlui-select__value\">\n\t\t\t\t{icon && <TldrawUiIcon icon={icon} label=\"\" small />}\n\t\t\t\t<span className=\"tlui-button__label\">{children}</span>\n\t\t\t</span>\n\t\t</_Select.Value>\n\t)\n}\n\n/* --------------------- Content --------------------- */\n\n/** @public */\nexport interface TLUiSelectContentProps {\n\tchildren: React.ReactNode\n\tside?: 'top' | 'bottom'\n\talign?: 'start' | 'center' | 'end'\n\tclassName?: string\n}\n\n/**\n * The dropdown content container for select items.\n *\n * @public\n * @react\n */\nexport function TldrawUiSelectContent({\n\tchildren,\n\tside = 'bottom',\n\talign = 'start',\n\tclassName,\n}: TLUiSelectContentProps) {\n\tconst container = useContainer()\n\n\treturn (\n\t\t<_Select.Portal container={container}>\n\t\t\t<_Select.Content\n\t\t\t\tclassName={classNames('tlui-menu tlui-select__content', className)}\n\t\t\t\tposition=\"popper\"\n\t\t\t\tside={side}\n\t\t\t\talign={align}\n\t\t\t\tsideOffset={4}\n\t\t\t\tcollisionPadding={4}\n\t\t\t>\n\t\t\t\t<_Select.Viewport className=\"tlui-select__viewport\">{children}</_Select.Viewport>\n\t\t\t</_Select.Content>\n\t\t</_Select.Portal>\n\t)\n}\n\n/* --------------------- Item --------------------- */\n\n/** @public */\nexport interface TLUiSelectItemProps {\n\tvalue: string\n\tlabel: string\n\ticon?: TLUiIconType | Exclude<string, TLUiIconType>\n\tdisabled?: boolean\n\tclassName?: string\n}\n\n/**\n * An item in the select dropdown. Styled to match TldrawUiMenuCheckboxItem.\n *\n * @public\n * @react\n */\nexport function TldrawUiSelectItem({\n\tvalue,\n\tlabel,\n\ticon,\n\tdisabled,\n\tclassName,\n}: TLUiSelectItemProps) {\n\treturn (\n\t\t<_Select.Item\n\t\t\tvalue={value}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={classNames(\n\t\t\t\t'tlui-button tlui-button__menu tlui-button__checkbox tlui-select__item',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t>\n\t\t\t<TldrawUiIcon small icon=\"check\" label=\"\" className=\"tlui-select__item-indicator\" />\n\t\t\t{icon && <TldrawUiIcon icon={icon} label=\"\" small />}\n\t\t\t<_Select.ItemText className=\"tlui-button__label\">{label}</_Select.ItemText>\n\t\t</_Select.Item>\n\t)\n}\n"],
|
|
5
|
+
"mappings": "AAgEG,cA6BA,YA7BA;AAhEH,SAAS,oBAAoB;AAC7B,OAAO,gBAAgB;AACvB,SAAS,UAAU,eAAe;AAClC,YAAY,WAAW;AACvB,SAAS,qBAAqB;AAE9B,SAAS,oBAAoB;AAoCtB,SAAS,eAAe;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,cAAc;AACf,GAAoB;AACnB,QAAM,CAAC,MAAM,gBAAgB,IAAI,cAAc,IAAI,YAAY;AAE/D,SACC;AAAA,IAAC,QAAQ;AAAA,IAAR;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA,KAAI;AAAA,MAEJ;AAAA,QAAC;AAAA;AAAA,UACA;AAAA,UACA,WAAW,WAAW,eAAe,SAAS;AAAA,UAC9C,eAAa;AAAA,UACb,cAAY;AAAA,UAEX;AAAA;AAAA,MACF;AAAA;AAAA,EACD;AAEF;AAgBO,MAAM,wBAAwB,MAAM;AAAA,EAC1C,SAASA,uBAAsB,EAAE,UAAU,UAAU,GAAG,KAAK;AAC5D,WACC;AAAA,MAAC,QAAQ;AAAA,MAAR;AAAA,QACA;AAAA,QACA,WAAW,WAAW,oCAAoC,SAAS;AAAA,QAElE;AAAA;AAAA,UACD,oBAAC,QAAQ,MAAR,EAAa,WAAU,wBACvB,8BAAC,gBAAa,MAAK,gBAAe,OAAM,IAAG,OAAK,MAAC,GAClD;AAAA;AAAA;AAAA,IACD;AAAA,EAEF;AACD;AAiBO,SAAS,oBAAoB,EAAE,aAAa,MAAM,SAAS,GAAyB;AAC1F,SACC,oBAAC,QAAQ,OAAR,EAAc,aACd,+BAAC,UAAK,WAAU,sBACd;AAAA,YAAQ,oBAAC,gBAAa,MAAY,OAAM,IAAG,OAAK,MAAC;AAAA,IAClD,oBAAC,UAAK,WAAU,sBAAsB,UAAS;AAAA,KAChD,GACD;AAEF;AAkBO,SAAS,sBAAsB;AAAA,EACrC;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR;AACD,GAA2B;AAC1B,QAAM,YAAY,aAAa;AAE/B,SACC,oBAAC,QAAQ,QAAR,EAAe,WACf;AAAA,IAAC,QAAQ;AAAA,IAAR;AAAA,MACA,WAAW,WAAW,kCAAkC,SAAS;AAAA,MACjE,UAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAElB,8BAAC,QAAQ,UAAR,EAAiB,WAAU,yBAAyB,UAAS;AAAA;AAAA,EAC/D,GACD;AAEF;AAmBO,SAAS,mBAAmB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,SACC;AAAA,IAAC,QAAQ;AAAA,IAAR;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACV;AAAA,QACA;AAAA,MACD;AAAA,MAEA;AAAA,4BAAC,gBAAa,OAAK,MAAC,MAAK,SAAQ,OAAM,IAAG,WAAU,+BAA8B;AAAA,QACjF,QAAQ,oBAAC,gBAAa,MAAY,OAAM,IAAG,OAAK,MAAC;AAAA,QAClD,oBAAC,QAAQ,UAAR,EAAiB,WAAU,sBAAsB,iBAAM;AAAA;AAAA;AAAA,EACzD;AAEF;",
|
|
6
|
+
"names": ["TldrawUiSelectTrigger"]
|
|
7
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const version = "4.4.0-canary.
|
|
1
|
+
const version = "4.4.0-canary.bb78e813fee7";
|
|
2
2
|
const publishDates = {
|
|
3
3
|
major: "2025-09-18T14:39:22.803Z",
|
|
4
|
-
minor: "2026-02-
|
|
5
|
-
patch: "2026-02-
|
|
4
|
+
minor: "2026-02-04T09:45:29.031Z",
|
|
5
|
+
patch: "2026-02-04T09:45:29.031Z"
|
|
6
6
|
};
|
|
7
7
|
export {
|
|
8
8
|
publishDates,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/ui/version.ts"],
|
|
4
|
-
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '4.4.0-canary.
|
|
4
|
+
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '4.4.0-canary.bb78e813fee7'\nexport const publishDates = {\n\tmajor: '2025-09-18T14:39:22.803Z',\n\tminor: '2026-02-04T09:45:29.031Z',\n\tpatch: '2026-02-04T09:45:29.031Z',\n}\n"],
|
|
5
5
|
"mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tldraw",
|
|
3
3
|
"description": "A tiny little drawing editor.",
|
|
4
|
-
"version": "4.4.0-canary.
|
|
4
|
+
"version": "4.4.0-canary.bb78e813fee7",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw Inc.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
"@tiptap/pm": "^3.12.1",
|
|
63
63
|
"@tiptap/react": "^3.12.1",
|
|
64
64
|
"@tiptap/starter-kit": "^3.12.1",
|
|
65
|
-
"@tldraw/editor": "4.4.0-canary.
|
|
66
|
-
"@tldraw/store": "4.4.0-canary.
|
|
65
|
+
"@tldraw/editor": "4.4.0-canary.bb78e813fee7",
|
|
66
|
+
"@tldraw/store": "4.4.0-canary.bb78e813fee7",
|
|
67
67
|
"classnames": "^2.5.1",
|
|
68
68
|
"hotkeys-js": "^3.13.9",
|
|
69
69
|
"idb": "^7.1.1",
|
package/src/index.ts
CHANGED
|
@@ -400,6 +400,7 @@ export {
|
|
|
400
400
|
TldrawUiDropdownMenuItem,
|
|
401
401
|
TldrawUiDropdownMenuRoot,
|
|
402
402
|
TldrawUiDropdownMenuSub,
|
|
403
|
+
TldrawUiDropdownMenuSubContent,
|
|
403
404
|
TldrawUiDropdownMenuSubTrigger,
|
|
404
405
|
TldrawUiDropdownMenuTrigger,
|
|
405
406
|
type TLUiDropdownMenuCheckboxItemProps,
|
|
@@ -407,6 +408,7 @@ export {
|
|
|
407
408
|
type TLUiDropdownMenuGroupProps,
|
|
408
409
|
type TLUiDropdownMenuItemProps,
|
|
409
410
|
type TLUiDropdownMenuRootProps,
|
|
411
|
+
type TLUiDropdownMenuSubContentProps,
|
|
410
412
|
type TLUiDropdownMenuSubProps,
|
|
411
413
|
type TLUiDropdownMenuSubTriggerProps,
|
|
412
414
|
type TLUiDropdownMenuTriggerProps,
|
|
@@ -426,6 +428,18 @@ export {
|
|
|
426
428
|
type TLUiPopoverProps,
|
|
427
429
|
type TLUiPopoverTriggerProps,
|
|
428
430
|
} from './lib/ui/components/primitives/TldrawUiPopover'
|
|
431
|
+
export {
|
|
432
|
+
TldrawUiSelect,
|
|
433
|
+
TldrawUiSelectContent,
|
|
434
|
+
TldrawUiSelectItem,
|
|
435
|
+
TldrawUiSelectTrigger,
|
|
436
|
+
TldrawUiSelectValue,
|
|
437
|
+
type TLUiSelectContentProps,
|
|
438
|
+
type TLUiSelectItemProps,
|
|
439
|
+
type TLUiSelectProps,
|
|
440
|
+
type TLUiSelectTriggerProps,
|
|
441
|
+
type TLUiSelectValueProps,
|
|
442
|
+
} from './lib/ui/components/primitives/TldrawUiSelect'
|
|
429
443
|
export { TldrawUiSlider, type TLUiSliderProps } from './lib/ui/components/primitives/TldrawUiSlider'
|
|
430
444
|
export {
|
|
431
445
|
TldrawUiToolbar,
|
|
@@ -671,7 +685,7 @@ export {
|
|
|
671
685
|
type TLUiTranslationContextType,
|
|
672
686
|
type TLUiTranslationProviderProps,
|
|
673
687
|
} from './lib/ui/hooks/useTranslation/useTranslation'
|
|
674
|
-
export { type TLUiIconType } from './lib/ui/icon-types'
|
|
688
|
+
export { iconTypes, type TLUiIconType } from './lib/ui/icon-types'
|
|
675
689
|
export { useDefaultHelpers, type TLUiOverrideHelpers, type TLUiOverrides } from './lib/ui/overrides'
|
|
676
690
|
export { TldrawUi, TldrawUiInFrontOfTheCanvas, type TldrawUiProps } from './lib/ui/TldrawUi'
|
|
677
691
|
export { containBoxSize, downsizeImage, type BoxWidthHeight } from './lib/utils/assets/assets'
|
|
@@ -58,8 +58,20 @@ export class ArrowBindingUtil extends BindingUtil<TLArrowBinding> {
|
|
|
58
58
|
|
|
59
59
|
// when the arrow itself changes
|
|
60
60
|
override onAfterChangeFromShape({
|
|
61
|
+
shapeBefore,
|
|
61
62
|
shapeAfter,
|
|
63
|
+
reason,
|
|
62
64
|
}: BindingOnShapeChangeOptions<TLArrowBinding>): void {
|
|
65
|
+
// When translating arrows together with their bound shapes, only x/y changes.
|
|
66
|
+
// In this case, bindings remain valid and no reparenting is needed.
|
|
67
|
+
// This is a significant performance optimization when moving many bound shapes.
|
|
68
|
+
if (
|
|
69
|
+
reason !== 'ancestry' &&
|
|
70
|
+
shapeBefore.parentId === shapeAfter.parentId &&
|
|
71
|
+
shapeBefore.index === shapeAfter.index
|
|
72
|
+
) {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
63
75
|
arrowDidUpdate(this.editor, shapeAfter as TLArrowShape)
|
|
64
76
|
}
|
|
65
77
|
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { useContainer } from '@tldraw/editor'
|
|
2
|
+
import classNames from 'classnames'
|
|
3
|
+
import { Select as _Select } from 'radix-ui'
|
|
4
|
+
import * as React from 'react'
|
|
5
|
+
import { useMenuIsOpen } from '../../hooks/useMenuIsOpen'
|
|
6
|
+
import { TLUiIconType } from '../../icon-types'
|
|
7
|
+
import { TldrawUiIcon } from './TldrawUiIcon'
|
|
8
|
+
|
|
9
|
+
/* --------------------- Root --------------------- */
|
|
10
|
+
|
|
11
|
+
/** @public */
|
|
12
|
+
export interface TLUiSelectProps {
|
|
13
|
+
id: string
|
|
14
|
+
value: string
|
|
15
|
+
onValueChange(value: string): void
|
|
16
|
+
onOpenChange?(isOpen: boolean): void
|
|
17
|
+
disabled?: boolean
|
|
18
|
+
className?: string
|
|
19
|
+
children: React.ReactNode
|
|
20
|
+
'data-testid'?: string
|
|
21
|
+
'aria-label'?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A select dropdown component.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <TldrawUiSelect id="my-select" value={value} onValueChange={setValue}>
|
|
30
|
+
* <TldrawUiSelectTrigger>
|
|
31
|
+
* <TldrawUiSelectValue placeholder="Select..." />
|
|
32
|
+
* </TldrawUiSelectTrigger>
|
|
33
|
+
* <TldrawUiSelectContent>
|
|
34
|
+
* <TldrawUiSelectItem value="one" label="One" />
|
|
35
|
+
* <TldrawUiSelectItem value="two" label="Two" />
|
|
36
|
+
* </TldrawUiSelectContent>
|
|
37
|
+
* </TldrawUiSelect>
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @public
|
|
41
|
+
* @react
|
|
42
|
+
*/
|
|
43
|
+
export function TldrawUiSelect({
|
|
44
|
+
id,
|
|
45
|
+
value,
|
|
46
|
+
onValueChange,
|
|
47
|
+
onOpenChange,
|
|
48
|
+
disabled,
|
|
49
|
+
className,
|
|
50
|
+
children,
|
|
51
|
+
'data-testid': dataTestId,
|
|
52
|
+
'aria-label': ariaLabel,
|
|
53
|
+
}: TLUiSelectProps) {
|
|
54
|
+
const [open, handleOpenChange] = useMenuIsOpen(id, onOpenChange)
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<_Select.Root
|
|
58
|
+
value={value}
|
|
59
|
+
onValueChange={onValueChange}
|
|
60
|
+
onOpenChange={handleOpenChange}
|
|
61
|
+
open={open}
|
|
62
|
+
disabled={disabled}
|
|
63
|
+
dir="ltr"
|
|
64
|
+
>
|
|
65
|
+
<div
|
|
66
|
+
id={id}
|
|
67
|
+
className={classNames('tlui-select', className)}
|
|
68
|
+
data-testid={dataTestId}
|
|
69
|
+
aria-label={ariaLabel}
|
|
70
|
+
>
|
|
71
|
+
{children}
|
|
72
|
+
</div>
|
|
73
|
+
</_Select.Root>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* --------------------- Trigger --------------------- */
|
|
78
|
+
|
|
79
|
+
/** @public */
|
|
80
|
+
export interface TLUiSelectTriggerProps {
|
|
81
|
+
children: React.ReactNode
|
|
82
|
+
className?: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The trigger button for the select dropdown.
|
|
87
|
+
*
|
|
88
|
+
* @public
|
|
89
|
+
* @react
|
|
90
|
+
*/
|
|
91
|
+
export const TldrawUiSelectTrigger = React.forwardRef<HTMLButtonElement, TLUiSelectTriggerProps>(
|
|
92
|
+
function TldrawUiSelectTrigger({ children, className }, ref) {
|
|
93
|
+
return (
|
|
94
|
+
<_Select.Trigger
|
|
95
|
+
ref={ref}
|
|
96
|
+
className={classNames('tlui-button tlui-select__trigger', className)}
|
|
97
|
+
>
|
|
98
|
+
{children}
|
|
99
|
+
<_Select.Icon className="tlui-select__chevron">
|
|
100
|
+
<TldrawUiIcon icon="chevron-down" label="" small />
|
|
101
|
+
</_Select.Icon>
|
|
102
|
+
</_Select.Trigger>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
/* --------------------- Value --------------------- */
|
|
108
|
+
|
|
109
|
+
/** @public */
|
|
110
|
+
export interface TLUiSelectValueProps {
|
|
111
|
+
placeholder?: string
|
|
112
|
+
icon?: TLUiIconType | Exclude<string, TLUiIconType>
|
|
113
|
+
children?: React.ReactNode
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Displays the currently selected value in the trigger.
|
|
118
|
+
*
|
|
119
|
+
* @public
|
|
120
|
+
* @react
|
|
121
|
+
*/
|
|
122
|
+
export function TldrawUiSelectValue({ placeholder, icon, children }: TLUiSelectValueProps) {
|
|
123
|
+
return (
|
|
124
|
+
<_Select.Value placeholder={placeholder}>
|
|
125
|
+
<span className="tlui-select__value">
|
|
126
|
+
{icon && <TldrawUiIcon icon={icon} label="" small />}
|
|
127
|
+
<span className="tlui-button__label">{children}</span>
|
|
128
|
+
</span>
|
|
129
|
+
</_Select.Value>
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* --------------------- Content --------------------- */
|
|
134
|
+
|
|
135
|
+
/** @public */
|
|
136
|
+
export interface TLUiSelectContentProps {
|
|
137
|
+
children: React.ReactNode
|
|
138
|
+
side?: 'top' | 'bottom'
|
|
139
|
+
align?: 'start' | 'center' | 'end'
|
|
140
|
+
className?: string
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The dropdown content container for select items.
|
|
145
|
+
*
|
|
146
|
+
* @public
|
|
147
|
+
* @react
|
|
148
|
+
*/
|
|
149
|
+
export function TldrawUiSelectContent({
|
|
150
|
+
children,
|
|
151
|
+
side = 'bottom',
|
|
152
|
+
align = 'start',
|
|
153
|
+
className,
|
|
154
|
+
}: TLUiSelectContentProps) {
|
|
155
|
+
const container = useContainer()
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<_Select.Portal container={container}>
|
|
159
|
+
<_Select.Content
|
|
160
|
+
className={classNames('tlui-menu tlui-select__content', className)}
|
|
161
|
+
position="popper"
|
|
162
|
+
side={side}
|
|
163
|
+
align={align}
|
|
164
|
+
sideOffset={4}
|
|
165
|
+
collisionPadding={4}
|
|
166
|
+
>
|
|
167
|
+
<_Select.Viewport className="tlui-select__viewport">{children}</_Select.Viewport>
|
|
168
|
+
</_Select.Content>
|
|
169
|
+
</_Select.Portal>
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/* --------------------- Item --------------------- */
|
|
174
|
+
|
|
175
|
+
/** @public */
|
|
176
|
+
export interface TLUiSelectItemProps {
|
|
177
|
+
value: string
|
|
178
|
+
label: string
|
|
179
|
+
icon?: TLUiIconType | Exclude<string, TLUiIconType>
|
|
180
|
+
disabled?: boolean
|
|
181
|
+
className?: string
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* An item in the select dropdown. Styled to match TldrawUiMenuCheckboxItem.
|
|
186
|
+
*
|
|
187
|
+
* @public
|
|
188
|
+
* @react
|
|
189
|
+
*/
|
|
190
|
+
export function TldrawUiSelectItem({
|
|
191
|
+
value,
|
|
192
|
+
label,
|
|
193
|
+
icon,
|
|
194
|
+
disabled,
|
|
195
|
+
className,
|
|
196
|
+
}: TLUiSelectItemProps) {
|
|
197
|
+
return (
|
|
198
|
+
<_Select.Item
|
|
199
|
+
value={value}
|
|
200
|
+
disabled={disabled}
|
|
201
|
+
className={classNames(
|
|
202
|
+
'tlui-button tlui-button__menu tlui-button__checkbox tlui-select__item',
|
|
203
|
+
className
|
|
204
|
+
)}
|
|
205
|
+
>
|
|
206
|
+
<TldrawUiIcon small icon="check" label="" className="tlui-select__item-indicator" />
|
|
207
|
+
{icon && <TldrawUiIcon icon={icon} label="" small />}
|
|
208
|
+
<_Select.ItemText className="tlui-button__label">{label}</_Select.ItemText>
|
|
209
|
+
</_Select.Item>
|
|
210
|
+
)
|
|
211
|
+
}
|
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.4.0-canary.
|
|
4
|
+
export const version = '4.4.0-canary.bb78e813fee7'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2025-09-18T14:39:22.803Z',
|
|
7
|
-
minor: '2026-02-
|
|
8
|
-
patch: '2026-02-
|
|
7
|
+
minor: '2026-02-04T09:45:29.031Z',
|
|
8
|
+
patch: '2026-02-04T09:45:29.031Z',
|
|
9
9
|
}
|
package/src/lib/ui.css
CHANGED
|
@@ -523,6 +523,52 @@
|
|
|
523
523
|
}
|
|
524
524
|
}
|
|
525
525
|
|
|
526
|
+
/* --------------------- Select --------------------- */
|
|
527
|
+
|
|
528
|
+
/* Trigger extends .tlui-button with space-between layout */
|
|
529
|
+
.tlui-select__trigger {
|
|
530
|
+
justify-content: space-between;
|
|
531
|
+
gap: var(--tl-space-3);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.tlui-select__trigger[data-state='open']::after {
|
|
535
|
+
opacity: 1;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.tlui-select__value {
|
|
539
|
+
display: flex;
|
|
540
|
+
align-items: center;
|
|
541
|
+
gap: var(--tl-space-2);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
.tlui-select__chevron {
|
|
545
|
+
flex-shrink: 0;
|
|
546
|
+
color: var(--tl-color-text-2);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/* Content extends .tlui-menu with Radix-aware sizing */
|
|
550
|
+
.tlui-select__content {
|
|
551
|
+
min-width: var(--radix-select-trigger-width);
|
|
552
|
+
max-height: var(--radix-select-content-available-height);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.tlui-select__viewport {
|
|
556
|
+
padding: 4px 0;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/* Item extends .tlui-button__checkbox with left-aligned text */
|
|
560
|
+
.tlui-select__item {
|
|
561
|
+
justify-content: flex-start;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.tlui-select__item-indicator {
|
|
565
|
+
visibility: hidden;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.tlui-select__item[data-state='checked'] .tlui-select__item-indicator {
|
|
569
|
+
visibility: visible;
|
|
570
|
+
}
|
|
571
|
+
|
|
526
572
|
/* ----------------------- Kbd ---------------------- */
|
|
527
573
|
|
|
528
574
|
.tlui-kbd {
|
package/tldraw.css
CHANGED
|
@@ -2323,6 +2323,52 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
2323
2323
|
}
|
|
2324
2324
|
}
|
|
2325
2325
|
|
|
2326
|
+
/* --------------------- Select --------------------- */
|
|
2327
|
+
|
|
2328
|
+
/* Trigger extends .tlui-button with space-between layout */
|
|
2329
|
+
.tlui-select__trigger {
|
|
2330
|
+
justify-content: space-between;
|
|
2331
|
+
gap: var(--tl-space-3);
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2334
|
+
.tlui-select__trigger[data-state='open']::after {
|
|
2335
|
+
opacity: 1;
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
.tlui-select__value {
|
|
2339
|
+
display: flex;
|
|
2340
|
+
align-items: center;
|
|
2341
|
+
gap: var(--tl-space-2);
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
.tlui-select__chevron {
|
|
2345
|
+
flex-shrink: 0;
|
|
2346
|
+
color: var(--tl-color-text-2);
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2349
|
+
/* Content extends .tlui-menu with Radix-aware sizing */
|
|
2350
|
+
.tlui-select__content {
|
|
2351
|
+
min-width: var(--radix-select-trigger-width);
|
|
2352
|
+
max-height: var(--radix-select-content-available-height);
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
.tlui-select__viewport {
|
|
2356
|
+
padding: 4px 0;
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2359
|
+
/* Item extends .tlui-button__checkbox with left-aligned text */
|
|
2360
|
+
.tlui-select__item {
|
|
2361
|
+
justify-content: flex-start;
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
.tlui-select__item-indicator {
|
|
2365
|
+
visibility: hidden;
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
.tlui-select__item[data-state='checked'] .tlui-select__item-indicator {
|
|
2369
|
+
visibility: visible;
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2326
2372
|
/* ----------------------- Kbd ---------------------- */
|
|
2327
2373
|
|
|
2328
2374
|
.tlui-kbd {
|