@noya-app/noya-designsystem 0.0.8 → 0.0.9

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,9 +1,12 @@
1
1
  {
2
2
  "name": "@noya-app/noya-designsystem",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": "./src/index.tsx"
9
+ },
7
10
  "scripts": {
8
11
  "build": "tsup src/index.tsx --format cjs,esm --dts --sourcemap",
9
12
  "dev": "npm run build -- --watch"
@@ -12,11 +15,11 @@
12
15
  "@dnd-kit/core": "3.1.1",
13
16
  "@dnd-kit/modifiers": "3.0.0",
14
17
  "@dnd-kit/sortable": "4.0.0",
15
- "@noya-app/noya-colorpicker": "0.0.4",
16
- "@noya-app/noya-utils": "0.0.7",
17
- "@noya-app/noya-geometry": "0.0.7",
18
- "@noya-app/noya-icons": "0.0.1",
19
- "@noya-app/noya-keymap": "0.0.3",
18
+ "@noya-app/noya-colorpicker": "workspace:*",
19
+ "@noya-app/noya-utils": "workspace:*",
20
+ "@noya-app/noya-geometry": "workspace:*",
21
+ "@noya-app/noya-icons": "workspace:*",
22
+ "@noya-app/noya-keymap": "workspace:*",
20
23
  "@radix-ui/primitive": "^1.0.0",
21
24
  "@radix-ui/react-avatar": "^1.0.1",
22
25
  "@radix-ui/react-compose-refs": "^1.0.0",
@@ -0,0 +1,66 @@
1
+ import { round } from "@noya-app/noya-utils";
2
+ import React, { memo, useCallback } from "react";
3
+ import { InputField } from "./InputField";
4
+
5
+ export type SetNumberMode = "replace" | "adjust";
6
+
7
+ export function getNewValue(
8
+ value: number,
9
+ mode: SetNumberMode,
10
+ delta?: number
11
+ ) {
12
+ return delta === undefined
13
+ ? value
14
+ : mode === "replace"
15
+ ? delta
16
+ : value + delta;
17
+ }
18
+
19
+ export type DimensionValue = number | undefined;
20
+
21
+ interface Props {
22
+ id?: string;
23
+ value: DimensionValue;
24
+ onSetValue: (value: number, mode: SetNumberMode) => void;
25
+ label?: string;
26
+ size?: number;
27
+ placeholder?: string;
28
+ disabled?: boolean;
29
+ trigger?: "change" | "submit";
30
+ }
31
+
32
+ export const DimensionInput = memo(function DimensionInput({
33
+ id,
34
+ value,
35
+ onSetValue,
36
+ label,
37
+ size,
38
+ placeholder = "multi",
39
+ disabled,
40
+ trigger = "submit",
41
+ }: Props) {
42
+ const handleNudgeValue = useCallback(
43
+ (value: number) => onSetValue(value, "adjust"),
44
+ [onSetValue]
45
+ );
46
+
47
+ const handleSetValue = useCallback(
48
+ (value: number) => onSetValue(value, "replace"),
49
+ [onSetValue]
50
+ );
51
+
52
+ return (
53
+ <InputField.Root id={id} width={size}>
54
+ <InputField.NumberInput
55
+ value={value === undefined ? value : round(value, 2)}
56
+ placeholder={value === undefined ? placeholder : undefined}
57
+ onNudge={handleNudgeValue}
58
+ disabled={disabled}
59
+ {...(trigger === "change"
60
+ ? { onChange: handleSetValue }
61
+ : { onSubmit: handleSetValue })}
62
+ />
63
+ {label && <InputField.Label>{label}</InputField.Label>}
64
+ </InputField.Root>
65
+ );
66
+ });
@@ -144,7 +144,7 @@ export const CompletionMenu = memo(
144
144
  })
145
145
  );
146
146
 
147
- interface Props {
147
+ type Props = {
148
148
  loading?: boolean;
149
149
  initialValue?: string;
150
150
  placeholder?: string;
@@ -160,7 +160,7 @@ interface Props {
160
160
  children?: React.ReactNode;
161
161
  hideChildrenWhenFocused?: boolean;
162
162
  hideMenuWhenEmptyValue?: boolean;
163
- }
163
+ };
164
164
 
165
165
  export const InputFieldWithCompletions = memo(
166
166
  forwardRef(function InputFieldWithCompletions(
@@ -1,143 +1,144 @@
1
- import { fireEvent, render } from '@testing-library/react';
2
- import React from 'react';
3
- import TextInput from '../TextInput';
4
-
5
- describe('submittable text input', () => {
6
- test('change and blur', () => {
7
- let text = '';
1
+ import { fireEvent, render } from "@testing-library/react";
2
+ import { describe, expect, mock, test } from "bun:test";
3
+ import React from "react";
4
+ import TextInput from "../TextInput";
5
+
6
+ describe("submittable text input", () => {
7
+ test("change and blur", () => {
8
+ let text = "";
8
9
  const handleSubmit = (value: string) => {
9
10
  text = value;
10
11
  };
11
12
 
12
13
  const { container, rerender } = render(
13
- <TextInput value={text} onSubmit={handleSubmit} />,
14
+ <TextInput value={text} onSubmit={handleSubmit} />
14
15
  );
15
16
 
16
- const input = container.querySelector('input')!;
17
- fireEvent.change(input, { target: { value: 'abc' } });
17
+ const input = container.querySelector("input")!;
18
+ fireEvent.change(input, { target: { value: "abc" } });
18
19
  fireEvent.blur(input);
19
20
 
20
- expect(text).toEqual('abc');
21
- expect(input.value).toEqual('');
21
+ expect(text).toEqual("abc");
22
+ expect(input.value).toEqual("");
22
23
 
23
24
  rerender(<TextInput value={text} onSubmit={handleSubmit} />);
24
25
 
25
- expect(input.value).toEqual('abc');
26
+ expect(input.value).toEqual("abc");
26
27
  });
27
28
 
28
- test('change and blur, reset', () => {
29
+ test("change and blur, reset", () => {
29
30
  const handleSubmit = (value: string) => {};
30
31
 
31
32
  const { container, rerender } = render(
32
- <TextInput value="" onSubmit={handleSubmit} />,
33
+ <TextInput value="" onSubmit={handleSubmit} />
33
34
  );
34
35
 
35
- const input = container.querySelector('input')!;
36
- fireEvent.change(input, { target: { value: 'abc' } });
36
+ const input = container.querySelector("input")!;
37
+ fireEvent.change(input, { target: { value: "abc" } });
37
38
  fireEvent.blur(input);
38
39
 
39
- expect(input.value).toEqual('');
40
+ expect(input.value).toEqual("");
40
41
 
41
42
  rerender(<TextInput value="def" onSubmit={handleSubmit} />);
42
43
 
43
- expect(input.value).toEqual('def');
44
+ expect(input.value).toEqual("def");
44
45
  });
45
46
 
46
- test('submit without changing', () => {
47
- const handleSubmit = jest.fn();
47
+ test("submit without changing", () => {
48
+ const handleSubmit = mock(() => {});
48
49
 
49
50
  const { container } = render(
50
- <TextInput value="" onSubmit={handleSubmit} />,
51
+ <TextInput value="" onSubmit={handleSubmit} />
51
52
  );
52
53
 
53
- const input = container.querySelector('input')!;
54
- fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
54
+ const input = container.querySelector("input")!;
55
+ fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
55
56
 
56
57
  expect(handleSubmit).not.toBeCalled();
57
58
  });
58
59
 
59
- test('change and submit', () => {
60
- let text = '';
60
+ test("change and submit", () => {
61
+ let text = "";
61
62
  const handleSubmit = (value: string) => {
62
63
  text = value;
63
64
  };
64
65
 
65
66
  const { container, rerender } = render(
66
- <TextInput value={text} onSubmit={handleSubmit} />,
67
+ <TextInput value={text} onSubmit={handleSubmit} />
67
68
  );
68
69
 
69
- const input = container.querySelector('input')!;
70
- fireEvent.change(input, { target: { value: 'abc' } });
71
- fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
70
+ const input = container.querySelector("input")!;
71
+ fireEvent.change(input, { target: { value: "abc" } });
72
+ fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
72
73
 
73
- expect(text).toEqual('abc');
74
- expect(input.value).toEqual('');
74
+ expect(text).toEqual("abc");
75
+ expect(input.value).toEqual("");
75
76
 
76
77
  rerender(<TextInput value={text} onSubmit={handleSubmit} />);
77
78
 
78
- expect(input.value).toEqual('abc');
79
+ expect(input.value).toEqual("abc");
79
80
 
80
- fireEvent.change(input, { target: { value: 'abcdef' } });
81
- fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
81
+ fireEvent.change(input, { target: { value: "abcdef" } });
82
+ fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
82
83
 
83
- expect(text).toEqual('abcdef');
84
- expect(input.value).toEqual('abc');
84
+ expect(text).toEqual("abcdef");
85
+ expect(input.value).toEqual("abc");
85
86
 
86
87
  rerender(<TextInput value={text} onSubmit={handleSubmit} />);
87
88
 
88
- expect(input.value).toEqual('abcdef');
89
+ expect(input.value).toEqual("abcdef");
89
90
  });
90
91
 
91
- test('change and submit, reset', () => {
92
+ test("change and submit, reset", () => {
92
93
  const handleSubmit = (value: string) => {};
93
94
 
94
95
  const { container, rerender } = render(
95
- <TextInput value="" onSubmit={handleSubmit} />,
96
+ <TextInput value="" onSubmit={handleSubmit} />
96
97
  );
97
98
 
98
- const input = container.querySelector('input')!;
99
- fireEvent.change(input, { target: { value: 'abc' } });
100
- fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
99
+ const input = container.querySelector("input")!;
100
+ fireEvent.change(input, { target: { value: "abc" } });
101
+ fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
101
102
 
102
- expect(input.value).toEqual('');
103
+ expect(input.value).toEqual("");
103
104
 
104
105
  rerender(<TextInput value="" onSubmit={handleSubmit} />);
105
106
 
106
- expect(input.value).toEqual('');
107
+ expect(input.value).toEqual("");
107
108
  });
108
109
 
109
- test('submit only once', () => {
110
- const handleSubmit = jest.fn();
110
+ test("submit only once", () => {
111
+ const handleSubmit = mock(() => {});
111
112
 
112
113
  const { container } = render(
113
- <TextInput value="" onSubmit={handleSubmit} />,
114
+ <TextInput value="" onSubmit={handleSubmit} />
114
115
  );
115
116
 
116
- const input = container.querySelector('input')!;
117
- fireEvent.change(input, { target: { value: 'abc' } });
118
- fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
119
- fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
120
- fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
117
+ const input = container.querySelector("input")!;
118
+ fireEvent.change(input, { target: { value: "abc" } });
119
+ fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
120
+ fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
121
+ fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
121
122
 
122
123
  expect(handleSubmit).toBeCalledTimes(1);
123
124
  });
124
125
 
125
- test('submit multiple times', () => {
126
- const handleSubmit = jest.fn();
126
+ test("submit multiple times", () => {
127
+ const handleSubmit = mock(() => {});
127
128
 
128
129
  const { container } = render(
129
130
  <TextInput
130
131
  value=""
131
132
  onSubmit={handleSubmit}
132
133
  allowSubmittingWithSameValue
133
- />,
134
+ />
134
135
  );
135
136
 
136
- const input = container.querySelector('input')!;
137
- fireEvent.change(input, { target: { value: 'abc' } });
138
- fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
139
- fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
140
- fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
137
+ const input = container.querySelector("input")!;
138
+ fireEvent.change(input, { target: { value: "abc" } });
139
+ fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
140
+ fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
141
+ fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
141
142
 
142
143
  expect(handleSubmit).toBeCalledTimes(3);
143
144
  });
package/src/index.tsx CHANGED
@@ -79,4 +79,5 @@ export { default as withSeparatorElements } from "./utils/withSeparatorElements"
79
79
 
80
80
  // Avoid dependency cycles
81
81
  export * as InspectorPrimitives from "./components/InspectorPrimitives";
82
- export * from "./components/ArrayController";
82
+ export * from "./components/ArrayController";
83
+ export * from "./components/DimensionInput";