@noya-app/noya-designsystem 0.1.28 → 0.1.30

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noya-app/noya-designsystem",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -64,39 +64,39 @@ const sizes: Record<
64
64
  };
65
65
 
66
66
  const Grid = styled.div<{
67
- size: GridViewSize;
68
- padding: CSSProperties["padding"];
69
- }>(({ theme, size, padding }) => {
67
+ $size: GridViewSize;
68
+ $padding: CSSProperties["padding"];
69
+ }>(({ theme, $size, $padding }) => {
70
70
  return {
71
71
  color: theme.colors.text,
72
72
  display: "grid",
73
- gridTemplateColumns: `repeat(auto-fill, minmax(${sizes[size].itemWidth}px, 1fr))`,
73
+ gridTemplateColumns: `repeat(auto-fill, minmax(${sizes[$size].itemWidth}px, 1fr))`,
74
74
  // gridAutoRows: `${sizes[size].itemHeight}px`,
75
- gap: `${sizes[size].gap}px`,
75
+ gap: `${sizes[$size].gap}px`,
76
76
  // gridTemplateColumns: `repeat(auto-fill, minmax(
77
77
  // ${size === 'large' ? '280px' : size === 'small' ? '160px' : '116px'}
78
78
  // , 1fr))`,
79
79
  // gridAutoRows:
80
80
  // size === 'large' ? '280px' : size === 'small' ? '170px' : '116px',
81
81
  // gap: size === 'large' || size === 'small' ? `20px` : `12px`,
82
- padding,
82
+ padding: $padding,
83
83
  };
84
84
  });
85
85
 
86
- const Container = styled.div<{ scrollable: boolean }>(
87
- ({ theme, scrollable }) => ({
88
- flex: scrollable ? "1" : "0 0 auto",
86
+ const Container = styled.div<{ $scrollable: boolean }>(
87
+ ({ theme, $scrollable }) => ({
88
+ flex: $scrollable ? "1" : "0 0 auto",
89
89
  display: "flex",
90
90
  flexDirection: "column",
91
91
  })
92
92
  );
93
93
 
94
94
  const ContentContainer = styled.div<{
95
- selected?: boolean;
96
- hovered?: boolean;
97
- bordered: boolean;
98
- disabled: boolean;
99
- }>(({ theme, selected, hovered, bordered, disabled }) => ({
95
+ $selected?: boolean;
96
+ $hovered?: boolean;
97
+ $bordered: boolean;
98
+ $disabled: boolean;
99
+ }>(({ theme, $selected, $hovered, $bordered, $disabled }) => ({
100
100
  display: "flex",
101
101
  flex: "1",
102
102
  backgroundColor: theme.colors.sidebar.background,
@@ -104,18 +104,18 @@ const ContentContainer = styled.div<{
104
104
  justifyContent: "center",
105
105
  borderRadius: "2px",
106
106
  border: `1px solid ${
107
- selected
107
+ $selected
108
108
  ? theme.colors.primary
109
109
  : // : hovered
110
110
  // ? `rgb(132, 63, 255, 0.5)`
111
- bordered
111
+ $bordered
112
112
  ? theme.colors.divider
113
113
  : "transparent"
114
114
  }`,
115
115
  overflow: "hidden",
116
116
 
117
117
  cursor: "pointer",
118
- ...(disabled
118
+ ...($disabled
119
119
  ? { opacity: 0.5 }
120
120
  : {
121
121
  "&:hover": { opacity: 0.85 },
@@ -134,8 +134,8 @@ const ItemContainer = styled.div(({ theme }) => ({
134
134
  },
135
135
  }));
136
136
 
137
- const ItemTitle = styled.span<{ showBackground: boolean }>(
138
- ({ theme, showBackground }) => ({
137
+ const ItemTitle = styled.span<{ $showBackground: boolean }>(
138
+ ({ theme, $showBackground }) => ({
139
139
  ...theme.textStyles.small,
140
140
  lineHeight: "1",
141
141
  color: theme.colors.text,
@@ -145,7 +145,7 @@ const ItemTitle = styled.span<{ showBackground: boolean }>(
145
145
  overflow: "hidden",
146
146
  textOverflow: "ellipsis",
147
147
 
148
- ...(showBackground && {
148
+ ...($showBackground && {
149
149
  background: theme.colors.sidebar.background,
150
150
  // border: `1px solid ${theme.colors.dividerSubtle}`,
151
151
  padding: "2px 4px",
@@ -155,8 +155,8 @@ const ItemTitle = styled.span<{ showBackground: boolean }>(
155
155
  })
156
156
  );
157
157
 
158
- const ItemDescription = styled.span<{ showBackground: boolean }>(
159
- ({ theme, showBackground }) => ({
158
+ const ItemDescription = styled.span<{ $showBackground: boolean }>(
159
+ ({ theme, $showBackground }) => ({
160
160
  ...theme.textStyles.small,
161
161
  fontSize: "0.7rem",
162
162
  lineHeight: "1",
@@ -166,7 +166,7 @@ const ItemDescription = styled.span<{ showBackground: boolean }>(
166
166
  overflow: "hidden",
167
167
  textOverflow: "ellipsis",
168
168
 
169
- ...(showBackground && {
169
+ ...($showBackground && {
170
170
  background: theme.colors.sidebar.background,
171
171
  // border: `1px solid ${theme.colors.dividerSubtle}`,
172
172
  padding: "2px 4px",
@@ -319,10 +319,10 @@ const GridViewItem = forwardRef(function GridViewItem<
319
319
  onKeyDown={handleKeyDown}
320
320
  >
321
321
  <ContentContainer
322
- disabled={disabled}
323
- bordered={bordered}
324
- selected={selected}
325
- hovered={!disabled && hovered}
322
+ $disabled={disabled}
323
+ $bordered={bordered}
324
+ $selected={selected}
325
+ $hovered={!disabled && hovered}
326
326
  onClick={handleClick}
327
327
  onDoubleClick={onDoubleClick}
328
328
  onContextMenu={onContextMenu}
@@ -333,17 +333,17 @@ const GridViewItem = forwardRef(function GridViewItem<
333
333
  {textPosition === "below" && (
334
334
  <>
335
335
  <Spacer.Vertical size={8} />
336
- <ItemTitle showBackground={false}>{title || " "}</ItemTitle>
337
- <ItemDescription showBackground={false}>
336
+ <ItemTitle $showBackground={false}>{title || " "}</ItemTitle>
337
+ <ItemDescription $showBackground={false}>
338
338
  {subtitle || " "}
339
339
  </ItemDescription>
340
340
  </>
341
341
  )}
342
342
  {textPosition === "overlay" && hovered && (title || subtitle) && (
343
343
  <TextOverlay>
344
- {title && <ItemTitle showBackground>{title}</ItemTitle>}
344
+ {title && <ItemTitle $showBackground>{title}</ItemTitle>}
345
345
  {subtitle && (
346
- <ItemDescription showBackground>{subtitle}</ItemDescription>
346
+ <ItemDescription $showBackground>{subtitle}</ItemDescription>
347
347
  )}
348
348
  </TextOverlay>
349
349
  )}
@@ -368,8 +368,10 @@ const GridViewItem = forwardRef(function GridViewItem<
368
368
  <Tooltip
369
369
  content={
370
370
  <Stack.V gap={2}>
371
- <ItemTitle showBackground={false}>{title}</ItemTitle>
372
- <ItemDescription showBackground={false}>{subtitle}</ItemDescription>
371
+ <ItemTitle $showBackground={false}>{title}</ItemTitle>
372
+ <ItemDescription $showBackground={false}>
373
+ {subtitle}
374
+ </ItemDescription>
373
375
  </Stack.V>
374
376
  }
375
377
  >
@@ -432,7 +434,7 @@ function GridViewRoot({
432
434
 
433
435
  return (
434
436
  <GridViewContext.Provider value={contextValue}>
435
- <Container onClick={handleClick} scrollable={scrollable}>
437
+ <Container onClick={handleClick} $scrollable={scrollable}>
436
438
  {scrollable ? <ScrollArea>{children}</ScrollArea> : children}
437
439
  </Container>
438
440
  </GridViewContext.Provider>
@@ -449,7 +451,7 @@ function GridViewSection({
449
451
  const { size } = useContext(GridViewContext);
450
452
 
451
453
  return (
452
- <Grid size={size} padding={padding}>
454
+ <Grid $size={size} $padding={padding}>
453
455
  {children}
454
456
  </Grid>
455
457
  );
@@ -35,6 +35,7 @@ type InputFieldContextValue = {
35
35
  labelSize: number;
36
36
  hasLabel: boolean;
37
37
  hasDropdown: boolean;
38
+ /** @default medium */
38
39
  size: InputFieldSize;
39
40
  isFocused: boolean;
40
41
  onFocusChange: (isFocused: boolean) => void;
@@ -543,9 +544,11 @@ interface InputFieldRootProps {
543
544
  flex?: string;
544
545
  children?: ReactNode;
545
546
  width?: number;
547
+ /** @default end */
546
548
  labelPosition?: LabelPosition;
547
549
  labelSize?: number;
548
550
  hasDropdown?: boolean;
551
+ /** @default medium */
549
552
  size?: InputFieldSize;
550
553
  renderPopoverContent?: (options: { width: number }) => ReactNode;
551
554
  onFocusChange?: (isFocused: boolean) => void;
@@ -317,6 +317,7 @@ interface ListViewRowProps<MenuItemType extends string = string> {
317
317
  id?: string;
318
318
  tabIndex?: number;
319
319
  selected?: boolean;
320
+ /** @default 0 */
320
321
  depth?: number;
321
322
  disabled?: boolean;
322
323
  // draggable?: boolean;
@@ -108,6 +108,7 @@ const ToggleGroupItem = forwardRef(function ToggleGroupItem(
108
108
  });
109
109
 
110
110
  type RadioGroupContextValue = {
111
+ /** @default primary */
111
112
  colorScheme?: RadioGroupColorScheme;
112
113
  };
113
114
 
@@ -119,6 +120,7 @@ interface Props {
119
120
  id?: string;
120
121
  value?: string;
121
122
  onValueChange?: (value: string) => void;
123
+ /** @default primary */
122
124
  colorScheme?: RadioGroupColorScheme;
123
125
  allowEmpty?: boolean;
124
126
  children: ReactNode;
@@ -44,6 +44,7 @@ const SwitchThumb = styled(SwitchPrimitive.Thumb)({
44
44
  interface Props {
45
45
  value: boolean;
46
46
  onChange: (value: boolean) => void;
47
+ /** @default normal */
47
48
  colorScheme?: SwitchColorScheme;
48
49
  disabled?: boolean;
49
50
  }
@@ -1,4 +1,7 @@
1
- import { useDesignSystemTheme } from "@noya-app/noya-designsystem";
1
+ import {
2
+ DesignSystemThemeProvider,
3
+ useDesignSystemTheme,
4
+ } from "@noya-app/noya-designsystem";
2
5
  import { useKeyboardShortcuts } from "@noya-app/noya-keymap";
3
6
  import React, { forwardRef, useImperativeHandle, useRef } from "react";
4
7
  import {
@@ -54,7 +57,7 @@ export type IWorkspaceLayout = {
54
57
  toggleRightSidebar: () => void;
55
58
  };
56
59
 
57
- export const WorkspaceLayout = forwardRef(function WorkspaceLayout(
60
+ const WorkspaceLayoutWithTheme = forwardRef(function WorkspaceLayoutWithTheme(
58
61
  {
59
62
  autoSavePrefix,
60
63
  leftSidebarContent: leftPanelContent,
@@ -260,3 +263,14 @@ export const WorkspaceLayout = forwardRef(function WorkspaceLayout(
260
263
  </div>
261
264
  );
262
265
  });
266
+
267
+ export const WorkspaceLayout = forwardRef(function WorkspaceLayout(
268
+ props: Props,
269
+ forwardedRef: React.ForwardedRef<IWorkspaceLayout>
270
+ ) {
271
+ return (
272
+ <DesignSystemThemeProvider>
273
+ <WorkspaceLayoutWithTheme {...props} ref={forwardedRef} />
274
+ </DesignSystemThemeProvider>
275
+ );
276
+ });
package/src/index.tsx CHANGED
@@ -84,6 +84,5 @@ export * from "./utils/sketchPattern";
84
84
  export { default as withSeparatorElements } from "./utils/withSeparatorElements";
85
85
 
86
86
  // Avoid dependency cycles
87
- export * from "./components/ArrayController";
88
87
  export * from "./components/DimensionInput";
89
88
  export * as InspectorPrimitives from "./components/InspectorPrimitives";
@@ -1,168 +0,0 @@
1
- import { range } from "@noya-app/noya-utils";
2
- import React, { ReactNode, memo, useCallback, useMemo } from "react";
3
- import styled, { useTheme } from "styled-components";
4
- import withSeparatorElements from "../utils/withSeparatorElements";
5
- import { Button } from "./Button";
6
- import { IconButton } from "./IconButton";
7
- import * as InspectorPrimitives from "./InspectorPrimitives";
8
- import { ListView } from "./ListView";
9
- import { RelativeDropPosition, Sortable } from "./Sortable";
10
- import { Spacer } from "./Spacer";
11
- import { Stack } from "./Stack";
12
-
13
- const ElementRow = styled.div({
14
- flex: "0 0 auto",
15
- display: "flex",
16
- flexDirection: "row",
17
- alignItems: "center",
18
- });
19
-
20
- const ItemContainer = styled.div({
21
- position: "relative",
22
- });
23
-
24
- export interface ArrayControllerProps<Item> {
25
- id: string;
26
- items: Item[];
27
- title: ReactNode;
28
- sortable?: boolean;
29
- reversed?: boolean;
30
- expanded?: boolean;
31
- getKey?: (item: Item) => string;
32
- onMoveItem?: (sourceIndex: number, destinationIndex: number) => void;
33
- onClickPlus?: () => void;
34
- onClickTrash?: () => void;
35
- onClickExpand?: () => void;
36
- renderItem: (props: { item: Item; index: number }) => ReactNode;
37
- renderExpandedContent?: () => ReactNode;
38
- padding?: number;
39
- }
40
-
41
- export const ArrayController = memo(function ArrayController<Item>({
42
- id,
43
- items,
44
- title,
45
- sortable = false,
46
- reversed = true,
47
- expanded = false,
48
- getKey,
49
- onMoveItem,
50
- onClickPlus,
51
- onClickTrash,
52
- onClickExpand,
53
- renderItem,
54
- renderExpandedContent,
55
- padding = 10,
56
- }: ArrayControllerProps<Item>) {
57
- const iconColor = useTheme().colors.icon;
58
- const primaryLightColor = useTheme().colors.primaryLight;
59
-
60
- const keys = useMemo(
61
- () => items.map((item, index) => getKey?.(item) ?? index.toString()),
62
- [getKey, items]
63
- );
64
-
65
- const indexes = reversed
66
- ? range(0, items.length).reverse()
67
- : range(0, items.length);
68
-
69
- const handleMoveItem = useCallback(
70
- (
71
- sourceIndex: number,
72
- destinationIndex: number,
73
- position: RelativeDropPosition
74
- ) => {
75
- if (reversed) {
76
- if (position === "above") {
77
- position = "below";
78
- } else if (position === "below") {
79
- position = "above";
80
- }
81
- }
82
-
83
- onMoveItem?.(
84
- sourceIndex,
85
- position === "below" ? destinationIndex + 1 : destinationIndex
86
- );
87
- },
88
- [onMoveItem, reversed]
89
- );
90
-
91
- const renderRow = (index: number) => {
92
- return (
93
- <ElementRow key={keys[index]}>
94
- {renderItem({ item: items[index], index: index })}
95
- </ElementRow>
96
- );
97
- };
98
-
99
- return (
100
- <InspectorPrimitives.Section id={id} $padding={padding} $gap="2px">
101
- <InspectorPrimitives.SectionHeader>
102
- <Button variant="none" onClick={onClickPlus}>
103
- <InspectorPrimitives.Title>{title}</InspectorPrimitives.Title>
104
- </Button>
105
- <Spacer.Horizontal />
106
- {withSeparatorElements(
107
- [
108
- onClickTrash && (
109
- <IconButton
110
- id={`${id}-trash`}
111
- iconName="TrashIcon"
112
- color={iconColor}
113
- onClick={onClickTrash}
114
- />
115
- ),
116
- onClickExpand && (
117
- <IconButton
118
- id={`${id}-gear`}
119
- iconName="GearIcon"
120
- color={expanded ? primaryLightColor : iconColor}
121
- onClick={onClickExpand}
122
- />
123
- ),
124
- onClickPlus && (
125
- <IconButton
126
- id={`${id}-add`}
127
- iconName="PlusIcon"
128
- color={iconColor}
129
- onClick={onClickPlus}
130
- />
131
- ),
132
- ],
133
- <Spacer.Horizontal size={8} />
134
- )}
135
- </InspectorPrimitives.SectionHeader>
136
- <Stack.V gap="4px">
137
- {sortable ? (
138
- <Sortable.Root
139
- keys={keys}
140
- renderOverlay={renderRow}
141
- onMoveItem={handleMoveItem}
142
- >
143
- {indexes.map((index) => (
144
- <Sortable.Item<HTMLDivElement> id={keys[index]} key={keys[index]}>
145
- {({ relativeDropPosition, ...sortableProps }) => (
146
- <ItemContainer {...sortableProps}>
147
- {renderRow(index)}
148
- {relativeDropPosition && (
149
- <ListView.DragIndicator
150
- $gap={0}
151
- $colorScheme="primary"
152
- $relativeDropPosition={relativeDropPosition}
153
- $offsetLeft={0}
154
- />
155
- )}
156
- </ItemContainer>
157
- )}
158
- </Sortable.Item>
159
- ))}
160
- </Sortable.Root>
161
- ) : (
162
- indexes.map(renderRow)
163
- )}
164
- </Stack.V>
165
- {expanded && renderExpandedContent?.()}
166
- </InspectorPrimitives.Section>
167
- );
168
- });