@workbench-kit/react 0.0.1-prototype.0 → 0.0.2-prototype.0.1.1

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.
Files changed (155) hide show
  1. package/package.json +33 -9
  2. package/src/index.ts +545 -43
  3. package/src/jdw/JdwPreview.tsx +38 -0
  4. package/src/jdw/JsonCodeEditorPane.tsx +274 -0
  5. package/src/jdw/builtins/renderBuiltinWidgetLeaf.tsx +29 -0
  6. package/src/jdw/builtins/renderBuiltinWidgetNode.tsx +126 -0
  7. package/src/jdw/createBuiltinJdwRegistry.ts +111 -0
  8. package/src/jdw/cssRenderBackend.tsx +134 -0
  9. package/src/jdw/document.ts +38 -0
  10. package/src/jdw/fixtures/jdw-fixtures.ts +52 -0
  11. package/src/jdw/fixtures/jdw-sample-screens.ts +522 -0
  12. package/src/jdw/index.ts +45 -0
  13. package/src/jdw/parse.ts +1 -0
  14. package/src/jdw/renderJdw.tsx +32 -0
  15. package/src/json-config/JsonConfigWorkbench.tsx +316 -0
  16. package/src/json-config/index.ts +6 -0
  17. package/src/json-config/json-config-editor-state.ts +42 -0
  18. package/src/layout/Panel.tsx +146 -1
  19. package/src/layout/SideBarViewFrame.tsx +367 -328
  20. package/src/layout/WorkbenchCanvas.tsx +849 -0
  21. package/src/layout/WorkbenchFullscreen.tsx +368 -0
  22. package/src/layout/WorkbenchLayout.tsx +5 -0
  23. package/src/layout/WorkbenchLayoutBase.tsx +294 -0
  24. package/src/layout/WorkbenchPropertyPanel.tsx +497 -0
  25. package/src/layout/WorkbenchSidebarActions.tsx +274 -0
  26. package/src/layout/WorkbenchTree.tsx +351 -0
  27. package/src/layout/layoutHelpers.ts +25 -0
  28. package/src/modal/ConfirmDialog.tsx +61 -53
  29. package/src/modal/Modal.tsx +295 -35
  30. package/src/overlay/ContextMenu.tsx +146 -145
  31. package/src/primitives/AbsoluteBox.tsx +46 -0
  32. package/src/primitives/Badge.tsx +12 -12
  33. package/src/primitives/Button.tsx +44 -14
  34. package/src/primitives/Checkbox.tsx +11 -5
  35. package/src/primitives/EmptyState.tsx +27 -26
  36. package/src/primitives/Field.tsx +38 -38
  37. package/src/primitives/IconButton.tsx +5 -2
  38. package/src/primitives/List.tsx +111 -0
  39. package/src/primitives/NumberInput.tsx +38 -0
  40. package/src/primitives/ScrollArea.tsx +42 -0
  41. package/src/primitives/Select.tsx +1 -12
  42. package/src/primitives/StatusBar.tsx +46 -0
  43. package/src/primitives/TextArea.tsx +36 -0
  44. package/src/primitives/TextInput.tsx +11 -2
  45. package/src/primitives/WorkbenchChrome.tsx +424 -0
  46. package/src/primitives/WorkbenchEditor.tsx +394 -0
  47. package/src/primitives/index.ts +105 -0
  48. package/src/primitives/select/Select.tsx +266 -0
  49. package/src/primitives/select/index.ts +2 -0
  50. package/src/primitives/select/options.ts +38 -0
  51. package/src/primitives/select/overlay.ts +63 -0
  52. package/src/primitives/select/select.app.css +9 -0
  53. package/src/primitives/select/select.css +140 -0
  54. package/src/primitives/select/types.ts +18 -0
  55. package/src/primitives/styles.css +955 -0
  56. package/src/scrollbars.css +69 -0
  57. package/src/styles.css +7738 -1762
  58. package/src/utils/codicon.ts +17 -0
  59. package/src/widget-asset/WidgetAssetEditor.tsx +140 -0
  60. package/src/widget-asset/WidgetAssetMetadataForm.tsx +82 -0
  61. package/src/widget-asset/WidgetAssetModeControls.tsx +42 -0
  62. package/src/widget-asset/WidgetAssetSourceEditor.tsx +50 -0
  63. package/src/widget-asset/WidgetAssetWorkbench.tsx +112 -0
  64. package/src/widget-asset/index.ts +17 -0
  65. package/src/widget-asset/widget-asset-document.ts +37 -0
  66. package/src/widget-asset/widget-asset-mode.ts +3 -0
  67. package/src/widget-studio/builtin-widget-asset-catalog.ts +12 -0
  68. package/src/widget-studio/create-widget-studio-workspace-editor.tsx +79 -0
  69. package/src/widget-studio/index.ts +7 -0
  70. package/src/widget-studio/resolve-widget-studio-asset-catalog.ts +26 -0
  71. package/src/widget-tree/WidgetAssetPalette.tsx +77 -0
  72. package/src/widget-tree/WidgetInspectorPanel.tsx +266 -0
  73. package/src/widget-tree/WidgetSourceEditor.tsx +56 -0
  74. package/src/widget-tree/WidgetTreeLab.tsx +272 -0
  75. package/src/widget-tree/WidgetTreeModeControls.tsx +44 -0
  76. package/src/widget-tree/WidgetTreeSidePanel.tsx +49 -0
  77. package/src/widget-tree/WidgetTreeView.tsx +97 -0
  78. package/src/widget-tree/WidgetTreeWorkbench.tsx +111 -0
  79. package/src/widget-tree/WidgetTreeWorkspaceShell.tsx +154 -0
  80. package/src/widget-tree/demo-registry.ts +32 -0
  81. package/src/widget-tree/demo-widget-assets.ts +4 -0
  82. package/src/widget-tree/index.ts +27 -0
  83. package/src/widget-tree/widget-tree-document.ts +20 -0
  84. package/src/widget-tree/widget-tree-layout.ts +31 -0
  85. package/src/widget-tree/widget-tree-mode.ts +7 -0
  86. package/src/widget-tree/widget-tree-play-helpers.ts +74 -0
  87. package/src/workbench/ActivityBar.tsx +52 -52
  88. package/src/workbench/ArtifactShell.tsx +397 -0
  89. package/src/workbench/CommandPalette.tsx +819 -0
  90. package/src/workbench/ConfirmationFlow.tsx +245 -0
  91. package/src/workbench/MarkdownPreview.tsx +151 -0
  92. package/src/workbench/ShortcutCommandBridge.tsx +368 -0
  93. package/src/workbench/SplitView.tsx +136 -136
  94. package/src/workbench/StatusBar.tsx +178 -123
  95. package/src/workbench/StructuredArtifactEditor.tsx +205 -0
  96. package/src/workbench/Timeline.tsx +302 -0
  97. package/src/workbench/WorkbenchCanvasShell.tsx +941 -0
  98. package/src/workbench/WorkbenchShell.tsx +74 -70
  99. package/src/workbench/WorkbenchStandaloneShell.tsx +318 -291
  100. package/src/workbench/auth/WorkbenchAuthGate.tsx +61 -0
  101. package/src/workbench/auth/WorkbenchLoginView.tsx +635 -0
  102. package/src/workbench/auth/index.ts +19 -0
  103. package/src/workbench/chat/ChatComposer.tsx +165 -148
  104. package/src/workbench/chat/ChatMessageItem.tsx +10 -1
  105. package/src/workbench/chat/index.ts +9 -0
  106. package/src/workbench/chat/slashCommand.ts +28 -0
  107. package/src/workbench/chat/useChatRuntimeState.ts +76 -0
  108. package/src/workbench/chat/useSlashCommandSuggest.ts +101 -0
  109. package/src/workbench/commands.ts +520 -490
  110. package/src/workbench/index.ts +443 -98
  111. package/src/workbench/keyboard.ts +53 -0
  112. package/src/workbench/schema/index.ts +48 -0
  113. package/src/workbench/schema/workbenchDocument.ts +31 -0
  114. package/src/workbench/schema/workbenchDocumentActions.ts +6 -0
  115. package/src/workbench/schema/workbenchDocumentAdapter.ts +9 -0
  116. package/src/workbench/schema/workbenchDocumentPatch.ts +13 -0
  117. package/src/workbench/schema/workbenchDocumentRenderer.tsx +702 -0
  118. package/src/workbench/settings/NavigationPanel.tsx +47 -0
  119. package/src/workbench/settings/SchemaForm.tsx +420 -0
  120. package/src/workbench/settings/SectionedPanel.tsx +415 -0
  121. package/src/workbench/settings/StructuredDataForm.tsx +539 -0
  122. package/src/workbench/settings/StructuredDataSchemaPanel.tsx +559 -0
  123. package/src/workbench/settings/StructuredDataSchemaPanelEmbed.tsx +21 -0
  124. package/src/workbench/settings/StructuredDataSchemaPanelFrame.tsx +76 -0
  125. package/src/workbench/settings/StructuredDataTableView.tsx +127 -0
  126. package/src/workbench/settings/WorkbenchPanelRegion.tsx +46 -0
  127. package/src/workbench/settings/WorkbenchSettingsModal.tsx +21 -12
  128. package/src/workbench/settings/WorkbenchSettingsNav.tsx +38 -22
  129. package/src/workbench/settings/index.ts +135 -0
  130. package/src/workbench/settings/panel-region.css +21 -0
  131. package/src/workbench/settings/sectionedPanelScrollSpy.ts +143 -0
  132. package/src/workbench/settings/structured-data-schema-panel.css +330 -0
  133. package/src/workbench/settings/structured-data-table-view.css +85 -0
  134. package/src/workbench/settings/structuredDataSchema.ts +886 -0
  135. package/src/workbench/shell.ts +15 -0
  136. package/src/workbench/shellState.ts +203 -203
  137. package/src/workbench/standalone.ts +101 -94
  138. package/src/workbench/status.ts +129 -0
  139. package/src/workbench/theme.ts +44 -0
  140. package/src/workbench/workspace/MultiProviderExplorer.tsx +625 -0
  141. package/src/workbench/workspace/WorkspaceDraftsContext.tsx +111 -0
  142. package/src/workbench/workspace/WorkspaceEditor.tsx +47 -12
  143. package/src/workbench/workspace/WorkspaceEditorPanel.tsx +334 -353
  144. package/src/workbench/workspace/WorkspaceExplorer.tsx +532 -524
  145. package/src/workbench/workspace/WorkspaceFileIcon.tsx +32 -2
  146. package/src/workbench/workspace/WorkspaceSearchPanel.tsx +113 -113
  147. package/src/workbench/workspace/WorkspaceSearchResults.tsx +47 -47
  148. package/src/workbench/workspace/index.ts +156 -98
  149. package/src/workbench/workspace/mimeType.ts +45 -0
  150. package/src/workbench/workspace/path.ts +10 -10
  151. package/src/workbench/workspace/search.ts +6 -6
  152. package/src/workbench/workspace/tree.ts +1 -1
  153. package/src/workbench/workspace/types.ts +10 -10
  154. package/src/workbench/workspace/useVirtualWorkspace.ts +111 -98
  155. package/src/workbench/workspace/workspaceJsonDiagnostics.ts +83 -0
@@ -1,145 +1,146 @@
1
- import { useEffect, useRef, useState, type ReactNode } from 'react';
2
- import { cx } from '../utils/cx';
3
-
4
- export type ContextMenuItem =
5
- | {
6
- type: 'separator';
7
- id?: string;
8
- }
9
- | {
10
- type?: 'item';
11
- id?: string;
12
- label: ReactNode;
13
- icon?: string;
14
- shortcut?: ReactNode;
15
- disabled?: boolean;
16
- danger?: boolean;
17
- onSelect: () => void;
18
- };
19
-
20
- export interface ContextMenuProps {
21
- ariaLabel?: string;
22
- className?: string;
23
- items: ContextMenuItem[];
24
- x: number;
25
- y: number;
26
- onClose: () => void;
27
- }
28
-
29
- function itemKey(item: ContextMenuItem, index: number): string {
30
- return item.id ?? `${item.type ?? 'item'}-${index}`;
31
- }
32
-
33
- export function ContextMenu({
34
- ariaLabel = 'Context menu',
35
- className,
36
- items,
37
- x,
38
- y,
39
- onClose,
40
- }: ContextMenuProps) {
41
- const ref = useRef<HTMLDivElement>(null);
42
- const [position, setPosition] = useState({ x, y });
43
-
44
- useEffect(() => {
45
- setPosition({ x, y });
46
- }, [x, y]);
47
-
48
- useEffect(() => {
49
- const menu = ref.current;
50
- if (!menu || typeof window === 'undefined') return;
51
-
52
- const frame = window.requestAnimationFrame(() => {
53
- const rect = menu.getBoundingClientRect();
54
- setPosition({
55
- x: Math.max(4, Math.min(x, window.innerWidth - rect.width - 4)),
56
- y: Math.max(4, Math.min(y, window.innerHeight - rect.height - 4)),
57
- });
58
- });
59
-
60
- return () => window.cancelAnimationFrame(frame);
61
- }, [items.length, x, y]);
62
-
63
- useEffect(() => {
64
- const handleKeyDown = (event: KeyboardEvent) => {
65
- if (event.key === 'Escape') {
66
- event.preventDefault();
67
- onClose();
68
- }
69
- };
70
-
71
- const handlePointerDown = (event: PointerEvent) => {
72
- if (ref.current?.contains(event.target as Node)) return;
73
- onClose();
74
- };
75
-
76
- const handleContextMenu = (event: MouseEvent) => {
77
- if (ref.current?.contains(event.target as Node)) {
78
- event.preventDefault();
79
- return;
80
- }
81
- onClose();
82
- };
83
-
84
- window.addEventListener('keydown', handleKeyDown);
85
- window.addEventListener('pointerdown', handlePointerDown, true);
86
- window.addEventListener('contextmenu', handleContextMenu, true);
87
- window.addEventListener('resize', onClose);
88
- window.addEventListener('scroll', onClose, true);
89
-
90
- return () => {
91
- window.removeEventListener('keydown', handleKeyDown);
92
- window.removeEventListener('pointerdown', handlePointerDown, true);
93
- window.removeEventListener('contextmenu', handleContextMenu, true);
94
- window.removeEventListener('resize', onClose);
95
- window.removeEventListener('scroll', onClose, true);
96
- };
97
- }, [onClose]);
98
-
99
- useEffect(() => {
100
- ref.current?.querySelector<HTMLButtonElement>('.ui-context-menu__item:not(:disabled)')?.focus();
101
- }, []);
102
-
103
- if (items.length === 0) return null;
104
-
105
- return (
106
- <div
107
- ref={ref}
108
- aria-label={ariaLabel}
109
- className={cx('ui-context-menu', className)}
110
- role="menu"
111
- style={{
112
- left: position.x,
113
- top: position.y,
114
- }}
115
- onContextMenu={(event) => event.preventDefault()}
116
- >
117
- {items.map((item, index) =>
118
- item.type === 'separator' ? (
119
- <div key={itemKey(item, index)} className="ui-context-menu__separator" role="separator" />
120
- ) : (
121
- <button
122
- key={itemKey(item, index)}
123
- className="ui-context-menu__item"
124
- data-danger={item.danger ? 'true' : undefined}
125
- disabled={item.disabled}
126
- role="menuitem"
127
- type="button"
128
- onClick={() => {
129
- item.onSelect();
130
- onClose();
131
- }}
132
- >
133
- <span className="ui-context-menu__icon">
134
- {item.icon ? <i className={`codicon ${item.icon}`} /> : null}
135
- </span>
136
- <span className="ui-context-menu__label">{item.label}</span>
137
- {item.shortcut ? (
138
- <span className="ui-context-menu__shortcut">{item.shortcut}</span>
139
- ) : null}
140
- </button>
141
- ),
142
- )}
143
- </div>
144
- );
145
- }
1
+ import { useEffect, useRef, useState, type ReactNode } from 'react';
2
+ import { cxCodicon } from '../utils/codicon';
3
+ import { cx } from '../utils/cx';
4
+
5
+ export type ContextMenuItem =
6
+ | {
7
+ type: 'separator';
8
+ id?: string | undefined;
9
+ }
10
+ | {
11
+ type?: 'item';
12
+ id?: string | undefined;
13
+ label: ReactNode;
14
+ icon?: string | undefined;
15
+ shortcut?: ReactNode | undefined;
16
+ disabled?: boolean | undefined;
17
+ danger?: boolean | undefined;
18
+ onSelect: () => void;
19
+ };
20
+
21
+ export interface ContextMenuProps {
22
+ ariaLabel?: string | undefined;
23
+ className?: string | undefined;
24
+ items: ContextMenuItem[];
25
+ x: number;
26
+ y: number;
27
+ onClose: () => void;
28
+ }
29
+
30
+ function itemKey(item: ContextMenuItem, index: number): string {
31
+ return item.id ?? `${item.type ?? 'item'}-${index}`;
32
+ }
33
+
34
+ export function ContextMenu({
35
+ ariaLabel = 'Context menu',
36
+ className,
37
+ items,
38
+ x,
39
+ y,
40
+ onClose,
41
+ }: ContextMenuProps) {
42
+ const ref = useRef<HTMLDivElement>(null);
43
+ const [position, setPosition] = useState({ x, y });
44
+
45
+ useEffect(() => {
46
+ setPosition({ x, y });
47
+ }, [x, y]);
48
+
49
+ useEffect(() => {
50
+ const menu = ref.current;
51
+ if (!menu || typeof window === 'undefined') return;
52
+
53
+ const frame = window.requestAnimationFrame(() => {
54
+ const rect = menu.getBoundingClientRect();
55
+ setPosition({
56
+ x: Math.max(4, Math.min(x, window.innerWidth - rect.width - 4)),
57
+ y: Math.max(4, Math.min(y, window.innerHeight - rect.height - 4)),
58
+ });
59
+ });
60
+
61
+ return () => window.cancelAnimationFrame(frame);
62
+ }, [items.length, x, y]);
63
+
64
+ useEffect(() => {
65
+ const handleKeyDown = (event: KeyboardEvent) => {
66
+ if (event.key === 'Escape') {
67
+ event.preventDefault();
68
+ onClose();
69
+ }
70
+ };
71
+
72
+ const handlePointerDown = (event: PointerEvent) => {
73
+ if (ref.current?.contains(event.target as Node)) return;
74
+ onClose();
75
+ };
76
+
77
+ const handleContextMenu = (event: MouseEvent) => {
78
+ if (ref.current?.contains(event.target as Node)) {
79
+ event.preventDefault();
80
+ return;
81
+ }
82
+ onClose();
83
+ };
84
+
85
+ window.addEventListener('keydown', handleKeyDown);
86
+ window.addEventListener('pointerdown', handlePointerDown, true);
87
+ window.addEventListener('contextmenu', handleContextMenu, true);
88
+ window.addEventListener('resize', onClose);
89
+ window.addEventListener('scroll', onClose, true);
90
+
91
+ return () => {
92
+ window.removeEventListener('keydown', handleKeyDown);
93
+ window.removeEventListener('pointerdown', handlePointerDown, true);
94
+ window.removeEventListener('contextmenu', handleContextMenu, true);
95
+ window.removeEventListener('resize', onClose);
96
+ window.removeEventListener('scroll', onClose, true);
97
+ };
98
+ }, [onClose]);
99
+
100
+ useEffect(() => {
101
+ ref.current?.querySelector<HTMLButtonElement>('.ui-context-menu__item:not(:disabled)')?.focus();
102
+ }, []);
103
+
104
+ if (items.length === 0) return null;
105
+
106
+ return (
107
+ <div
108
+ ref={ref}
109
+ aria-label={ariaLabel}
110
+ className={cx('ui-context-menu', className)}
111
+ role="menu"
112
+ style={{
113
+ left: position.x,
114
+ top: position.y,
115
+ }}
116
+ onContextMenu={(event) => event.preventDefault()}
117
+ >
118
+ {items.map((item, index) =>
119
+ item.type === 'separator' ? (
120
+ <div key={itemKey(item, index)} className="ui-context-menu__separator" role="separator" />
121
+ ) : (
122
+ <button
123
+ key={itemKey(item, index)}
124
+ className="ui-context-menu__item"
125
+ data-danger={item.danger ? 'true' : undefined}
126
+ disabled={item.disabled}
127
+ role="menuitem"
128
+ type="button"
129
+ onClick={() => {
130
+ item.onSelect();
131
+ onClose();
132
+ }}
133
+ >
134
+ <span className="ui-context-menu__icon">
135
+ {item.icon ? <i className={cxCodicon(item.icon)} /> : null}
136
+ </span>
137
+ <span className="ui-context-menu__label">{item.label}</span>
138
+ {item.shortcut ? (
139
+ <span className="ui-context-menu__shortcut">{item.shortcut}</span>
140
+ ) : null}
141
+ </button>
142
+ ),
143
+ )}
144
+ </div>
145
+ );
146
+ }
@@ -0,0 +1,46 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+ import { cx } from '../utils/cx';
3
+
4
+ export interface WorkbenchRect {
5
+ x: number;
6
+ y: number;
7
+ width: number;
8
+ height: number;
9
+ }
10
+
11
+ export interface AbsoluteBoxProps {
12
+ background?: string | undefined;
13
+ children?: ReactNode;
14
+ className?: string | undefined;
15
+ overflow?: CSSProperties['overflow'] | undefined;
16
+ rect: WorkbenchRect;
17
+ style?: CSSProperties | undefined;
18
+ }
19
+
20
+ export function AbsoluteBox({
21
+ background,
22
+ children,
23
+ className,
24
+ overflow = 'hidden',
25
+ rect,
26
+ style,
27
+ }: AbsoluteBoxProps) {
28
+ return (
29
+ <div
30
+ className={cx('ui-absolute-box', className)}
31
+ style={{
32
+ position: 'absolute',
33
+ left: rect.x,
34
+ top: rect.y,
35
+ width: rect.width,
36
+ height: rect.height,
37
+ overflow,
38
+ backgroundColor: background,
39
+ boxSizing: 'border-box',
40
+ ...style,
41
+ }}
42
+ >
43
+ {children}
44
+ </div>
45
+ );
46
+ }
@@ -1,12 +1,12 @@
1
- import type { ComponentPropsWithRef } from 'react';
2
- import { cx } from '../utils/cx';
3
-
4
- type BadgeVariant = 'accent' | 'muted' | 'danger';
5
-
6
- export interface BadgeProps extends ComponentPropsWithRef<'span'> {
7
- variant?: BadgeVariant;
8
- }
9
-
10
- export function Badge({ className, variant = 'accent', ...props }: BadgeProps) {
11
- return <span className={cx('ui-badge', className)} data-variant={variant} {...props} />;
12
- }
1
+ import type { ComponentPropsWithRef } from 'react';
2
+ import { cx } from '../utils/cx';
3
+
4
+ type BadgeVariant = 'accent' | 'muted' | 'danger';
5
+
6
+ export interface BadgeProps extends ComponentPropsWithRef<'span'> {
7
+ variant?: BadgeVariant;
8
+ }
9
+
10
+ export function Badge({ className, variant = 'accent', ...props }: BadgeProps) {
11
+ return <span className={cx('ui-badge', className)} data-variant={variant} {...props} />;
12
+ }
@@ -1,14 +1,44 @@
1
- import type { ComponentPropsWithRef } from 'react';
2
- import { cx } from '../utils/cx';
3
-
4
- type ButtonVariant = 'default' | 'primary' | 'danger';
5
-
6
- export interface ButtonProps extends ComponentPropsWithRef<'button'> {
7
- variant?: ButtonVariant;
8
- }
9
-
10
- export function Button({ className, type = 'button', variant = 'default', ...props }: ButtonProps) {
11
- return (
12
- <button className={cx('ui-button', className)} data-variant={variant} type={type} {...props} />
13
- );
14
- }
1
+ import type { ComponentPropsWithRef } from 'react';
2
+ import { cxCodicon } from '../utils/codicon';
3
+ import { cx } from '../utils/cx';
4
+
5
+ type ButtonVariant = 'default' | 'primary' | 'danger';
6
+
7
+ export interface ButtonProps extends ComponentPropsWithRef<'button'> {
8
+ block?: boolean | undefined;
9
+ compact?: boolean | undefined;
10
+ icon?: string | undefined;
11
+ secondary?: boolean | undefined;
12
+ variant?: ButtonVariant;
13
+ }
14
+
15
+ export function Button({
16
+ block = false,
17
+ children,
18
+ className,
19
+ compact = false,
20
+ icon,
21
+ secondary: _secondary,
22
+ type = 'button',
23
+ variant = 'default',
24
+ ...props
25
+ }: ButtonProps) {
26
+ const iconClassName = cxCodicon(icon);
27
+
28
+ return (
29
+ <button
30
+ className={cx(
31
+ 'ui-button',
32
+ block && 'ui-button--block',
33
+ compact && 'ui-button--compact',
34
+ className,
35
+ )}
36
+ data-variant={variant}
37
+ type={type}
38
+ {...props}
39
+ >
40
+ {iconClassName ? <i className={iconClassName} aria-hidden /> : null}
41
+ {children}
42
+ </button>
43
+ );
44
+ }
@@ -1,15 +1,21 @@
1
- import type { ComponentPropsWithRef, ReactNode } from 'react';
1
+ import type { ChangeEvent, ComponentPropsWithRef, ReactNode } from 'react';
2
2
  import { cx } from '../utils/cx';
3
3
 
4
4
  export interface CheckboxProps extends Omit<ComponentPropsWithRef<'input'>, 'type'> {
5
- label: ReactNode;
5
+ label?: ReactNode | undefined;
6
+ onCheckedChange?: (checked: boolean, event: ChangeEvent<HTMLInputElement>) => void;
6
7
  }
7
8
 
8
- export function Checkbox({ className, label, ...props }: CheckboxProps) {
9
+ export function Checkbox({ className, label, onChange, onCheckedChange, ...props }: CheckboxProps) {
10
+ const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
11
+ onChange?.(event);
12
+ onCheckedChange?.(event.currentTarget.checked, event);
13
+ };
14
+
9
15
  return (
10
16
  <label className={cx('ui-checkbox', className)}>
11
- <input type="checkbox" {...props} />
12
- <span>{label}</span>
17
+ <input type="checkbox" onChange={handleChange} {...props} />
18
+ {label !== undefined && label !== null && label !== '' ? <span>{label}</span> : null}
13
19
  </label>
14
20
  );
15
21
  }
@@ -1,26 +1,27 @@
1
- import type { ComponentPropsWithRef, ReactNode } from 'react';
2
- import { cx } from '../utils/cx';
3
-
4
- export interface EmptyStateProps extends ComponentPropsWithRef<'div'> {
5
- compact?: boolean;
6
- icon: string;
7
- children: ReactNode;
8
- }
9
-
10
- export function EmptyState({
11
- children,
12
- className,
13
- compact = false,
14
- icon,
15
- ...props
16
- }: EmptyStateProps) {
17
- return (
18
- <div
19
- className={cx('ui-empty-state', compact && 'ui-empty-state--compact', className)}
20
- {...props}
21
- >
22
- <i className={`codicon ${icon}`} />
23
- <span>{children}</span>
24
- </div>
25
- );
26
- }
1
+ import type { ComponentPropsWithRef, ReactNode } from 'react';
2
+ import { cxCodicon } from '../utils/codicon';
3
+ import { cx } from '../utils/cx';
4
+
5
+ export interface EmptyStateProps extends ComponentPropsWithRef<'div'> {
6
+ compact?: boolean;
7
+ icon: string;
8
+ children: ReactNode;
9
+ }
10
+
11
+ export function EmptyState({
12
+ children,
13
+ className,
14
+ compact = false,
15
+ icon,
16
+ ...props
17
+ }: EmptyStateProps) {
18
+ return (
19
+ <div
20
+ className={cx('ui-empty-state', compact && 'ui-empty-state--compact', className)}
21
+ {...props}
22
+ >
23
+ <i className={cxCodicon(icon)} />
24
+ <span>{children}</span>
25
+ </div>
26
+ );
27
+ }
@@ -1,38 +1,38 @@
1
- import type { ReactNode } from 'react';
2
- import { cx } from '../utils/cx';
3
-
4
- export interface FieldProps {
5
- children: ReactNode;
6
- className?: string;
7
- description?: ReactNode;
8
- htmlFor?: string;
9
- inline?: boolean;
10
- label?: ReactNode;
11
- }
12
-
13
- export function Field({
14
- label,
15
- children,
16
- className,
17
- description,
18
- htmlFor,
19
- inline = false,
20
- }: FieldProps) {
21
- const labelElement = !label ? null : htmlFor ? (
22
- <label className="ui-field__label" htmlFor={htmlFor}>
23
- {label}
24
- </label>
25
- ) : (
26
- <span className="ui-field__label">{label}</span>
27
- );
28
-
29
- return (
30
- <div className={cx('ui-field', inline && 'ui-field--inline', className)}>
31
- <div>
32
- {labelElement}
33
- {description && <div className="ui-field__description">{description}</div>}
34
- </div>
35
- {children}
36
- </div>
37
- );
38
- }
1
+ import type { ReactNode } from 'react';
2
+ import { cx } from '../utils/cx';
3
+
4
+ export interface FieldProps {
5
+ children: ReactNode;
6
+ className?: string;
7
+ description?: ReactNode;
8
+ htmlFor?: string;
9
+ inline?: boolean;
10
+ label?: ReactNode;
11
+ }
12
+
13
+ export function Field({
14
+ label,
15
+ children,
16
+ className,
17
+ description,
18
+ htmlFor,
19
+ inline = false,
20
+ }: FieldProps) {
21
+ const labelElement = !label ? null : htmlFor ? (
22
+ <label className="ui-field__label" htmlFor={htmlFor}>
23
+ {label}
24
+ </label>
25
+ ) : (
26
+ <span className="ui-field__label">{label}</span>
27
+ );
28
+
29
+ return (
30
+ <div className={cx('ui-field', inline && 'ui-field--inline', className)}>
31
+ <div>
32
+ {labelElement}
33
+ {description && <div className="ui-field__description">{description}</div>}
34
+ </div>
35
+ {children}
36
+ </div>
37
+ );
38
+ }
@@ -1,9 +1,11 @@
1
1
  import type { ComponentPropsWithRef } from 'react';
2
+ import { cxCodicon } from '../utils/codicon';
2
3
  import { cx } from '../utils/cx';
3
4
 
4
5
  type IconButtonVariant = 'default' | 'danger';
5
6
 
6
7
  export interface IconButtonProps extends Omit<ComponentPropsWithRef<'button'>, 'children'> {
8
+ compact?: boolean | undefined;
7
9
  icon: string;
8
10
  label: string;
9
11
  variant?: IconButtonVariant;
@@ -11,6 +13,7 @@ export interface IconButtonProps extends Omit<ComponentPropsWithRef<'button'>, '
11
13
 
12
14
  export function IconButton({
13
15
  className,
16
+ compact = false,
14
17
  icon,
15
18
  label,
16
19
  type = 'button',
@@ -20,13 +23,13 @@ export function IconButton({
20
23
  return (
21
24
  <button
22
25
  aria-label={label}
23
- className={cx('ui-icon-button', className)}
26
+ className={cx('ui-icon-button', compact && 'ui-icon-button--compact', className)}
24
27
  data-variant={variant}
25
28
  title={label}
26
29
  type={type}
27
30
  {...props}
28
31
  >
29
- <i className={`codicon ${icon}`} />
32
+ <i className={cxCodicon(icon)} />
30
33
  </button>
31
34
  );
32
35
  }