@tcn/ui 0.12.5 → 0.12.7

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 (131) hide show
  1. package/dist/aside.css +1 -0
  2. package/dist/inputs/color_input/color_input.js +18 -18
  3. package/dist/inputs/color_input/color_input.js.map +1 -1
  4. package/dist/inputs/control/control.d.ts +10 -0
  5. package/dist/inputs/control/control.d.ts.map +1 -0
  6. package/dist/inputs/control/control.js +17 -0
  7. package/dist/inputs/control/control.js.map +1 -0
  8. package/dist/inputs/control_set/control_set.d.ts +5 -0
  9. package/dist/inputs/control_set/control_set.d.ts.map +1 -0
  10. package/dist/inputs/control_set/control_set.js +20 -0
  11. package/dist/inputs/{input_group/input_group.js.map → control_set/control_set.js.map} +1 -1
  12. package/dist/inputs/date_picker/date_picker_input.js +20 -20
  13. package/dist/inputs/date_picker/date_picker_input.js.map +1 -1
  14. package/dist/inputs/index.d.ts +2 -1
  15. package/dist/inputs/index.d.ts.map +1 -1
  16. package/dist/inputs/index.js +27 -24
  17. package/dist/inputs/index.js.map +1 -1
  18. package/dist/inputs/input/input.js +6 -6
  19. package/dist/inputs/input/input.js.map +1 -1
  20. package/dist/inputs/phone_number_input/phone_number_country_select_adapter.js +15 -15
  21. package/dist/inputs/phone_number_input/phone_number_country_select_adapter.js.map +1 -1
  22. package/dist/inputs/phone_number_input/phone_number_input.js +24 -24
  23. package/dist/inputs/phone_number_input/phone_number_input.js.map +1 -1
  24. package/dist/inputs/phone_number_input/phone_number_input_adapter.js +21 -21
  25. package/dist/inputs/phone_number_input/phone_number_input_adapter.js.map +1 -1
  26. package/dist/inputs/phone_number_input/sip_input.js +14 -14
  27. package/dist/inputs/phone_number_input/sip_input.js.map +1 -1
  28. package/dist/inputs/select/select.js +6 -6
  29. package/dist/inputs/select/select.js.map +1 -1
  30. package/dist/inputs/textarea/textarea.js +8 -8
  31. package/dist/inputs/textarea/textarea.js.map +1 -1
  32. package/dist/inputs/unit_input/unit_input.js +20 -20
  33. package/dist/inputs/unit_input/unit_input.js.map +1 -1
  34. package/dist/overlay/frame/frame.d.ts +2 -2
  35. package/dist/overlay/frame/frame.d.ts.map +1 -1
  36. package/dist/overlay/frame/frame.js +67 -59
  37. package/dist/overlay/frame/frame.js.map +1 -1
  38. package/dist/overlay/slide/slide.d.ts +9 -0
  39. package/dist/overlay/slide/slide.d.ts.map +1 -0
  40. package/dist/overlay/slide/slide.js +29 -0
  41. package/dist/overlay/slide/slide.js.map +1 -0
  42. package/dist/slide.css +1 -0
  43. package/dist/surfaces/aside/aside.d.ts +5 -0
  44. package/dist/surfaces/aside/aside.d.ts.map +1 -0
  45. package/dist/surfaces/aside/aside.js +19 -0
  46. package/dist/surfaces/aside/aside.js.map +1 -0
  47. package/dist/surfaces/drawers/drawer.d.ts +5 -0
  48. package/dist/surfaces/drawers/drawer.d.ts.map +1 -0
  49. package/dist/surfaces/drawers/drawer.js +23 -0
  50. package/dist/surfaces/drawers/drawer.js.map +1 -0
  51. package/dist/surfaces/index.d.ts +2 -4
  52. package/dist/surfaces/index.d.ts.map +1 -1
  53. package/dist/surfaces/index.js +22 -26
  54. package/dist/surfaces/index.js.map +1 -1
  55. package/dist/surfaces/modal/modal.d.ts +1 -1
  56. package/dist/surfaces/modal/modal.d.ts.map +1 -1
  57. package/dist/surfaces/window/window.d.ts +1 -1
  58. package/dist/surfaces/window/window.d.ts.map +1 -1
  59. package/dist/themes/stylesheets/reset.css +1 -1
  60. package/dist/themes/stylesheets/reset.js +2 -2
  61. package/dist/themes/stylesheets/reset.js.map +1 -1
  62. package/dist/themes/themes/ergo/ergo_theme.css +1 -1
  63. package/dist/themes/themes/ergo/ergo_theme.js +95 -8
  64. package/dist/themes/themes/ergo/ergo_theme.js.map +1 -1
  65. package/dist/utils/dnd/hooks/use_drag_container.d.ts.map +1 -1
  66. package/dist/utils/dnd/hooks/use_drag_container.js.map +1 -1
  67. package/package.json +2 -2
  68. package/src/inputs/color_input/color_input.tsx +3 -3
  69. package/src/inputs/control/control.stories.tsx +158 -0
  70. package/src/inputs/control/control.tsx +32 -0
  71. package/src/inputs/control/control_stories.module.css +7 -0
  72. package/src/inputs/control_set/control_set.stories.tsx +46 -0
  73. package/src/inputs/{input_group/input_group.tsx → control_set/control_set.tsx} +5 -5
  74. package/src/inputs/date_picker/date_picker_input.stories.tsx +1 -1
  75. package/src/inputs/date_picker/date_picker_input.tsx +1 -1
  76. package/src/inputs/index.ts +2 -1
  77. package/src/inputs/input/input.tsx +1 -1
  78. package/src/inputs/phone_number_input/phone_number_country_select_adapter.tsx +1 -1
  79. package/src/inputs/phone_number_input/phone_number_input.tsx +1 -1
  80. package/src/inputs/phone_number_input/phone_number_input_adapter.tsx +2 -2
  81. package/src/inputs/phone_number_input/sip_input.tsx +4 -4
  82. package/src/inputs/select/select.tsx +1 -1
  83. package/src/inputs/textarea/textarea.stories.tsx +1 -1
  84. package/src/inputs/textarea/textarea.tsx +1 -1
  85. package/src/inputs/unit_input/unit_input.tsx +3 -3
  86. package/src/overlay/frame/frame.tsx +13 -16
  87. package/src/overlay/slide/slide.module.css +30 -0
  88. package/src/overlay/slide/slide.stories.tsx +58 -0
  89. package/src/overlay/slide/slide.tsx +51 -0
  90. package/src/surfaces/aside/aside.module.css +5 -0
  91. package/src/surfaces/aside/aside.stories.tsx +56 -0
  92. package/src/surfaces/aside/aside.tsx +22 -0
  93. package/src/surfaces/drawers/drawer.stories.tsx +130 -0
  94. package/src/surfaces/drawers/drawer.tsx +26 -0
  95. package/src/surfaces/index.ts +2 -4
  96. package/src/themes/stylesheets/reset.css +2 -2
  97. package/src/themes/themes/ergo/ergo_theme.css +95 -8
  98. package/src/utils/dnd/hooks/use_drag_container.ts +0 -7
  99. package/tsconfig.json +5 -33
  100. package/dist/drawer_bottom.css +0 -1
  101. package/dist/drawer_end.css +0 -1
  102. package/dist/drawer_start.css +0 -1
  103. package/dist/drawer_top.css +0 -1
  104. package/dist/inputs/input_group/input_group.d.ts +0 -5
  105. package/dist/inputs/input_group/input_group.d.ts.map +0 -1
  106. package/dist/inputs/input_group/input_group.js +0 -20
  107. package/dist/surfaces/drawers/drawer_bottom/drawer_bottom.d.ts +0 -7
  108. package/dist/surfaces/drawers/drawer_bottom/drawer_bottom.d.ts.map +0 -1
  109. package/dist/surfaces/drawers/drawer_bottom/drawer_bottom.js +0 -22
  110. package/dist/surfaces/drawers/drawer_bottom/drawer_bottom.js.map +0 -1
  111. package/dist/surfaces/drawers/drawer_end/drawer_end.d.ts +0 -7
  112. package/dist/surfaces/drawers/drawer_end/drawer_end.d.ts.map +0 -1
  113. package/dist/surfaces/drawers/drawer_end/drawer_end.js +0 -20
  114. package/dist/surfaces/drawers/drawer_end/drawer_end.js.map +0 -1
  115. package/dist/surfaces/drawers/drawer_start/drawer_start.d.ts +0 -7
  116. package/dist/surfaces/drawers/drawer_start/drawer_start.d.ts.map +0 -1
  117. package/dist/surfaces/drawers/drawer_start/drawer_start.js +0 -22
  118. package/dist/surfaces/drawers/drawer_start/drawer_start.js.map +0 -1
  119. package/dist/surfaces/drawers/drawer_top/drawer_top.d.ts +0 -7
  120. package/dist/surfaces/drawers/drawer_top/drawer_top.d.ts.map +0 -1
  121. package/dist/surfaces/drawers/drawer_top/drawer_top.js +0 -20
  122. package/dist/surfaces/drawers/drawer_top/drawer_top.js.map +0 -1
  123. package/src/surfaces/drawers/__stories__/drawers.stories.tsx +0 -26
  124. package/src/surfaces/drawers/drawer_bottom/drawer_bottom.module.css +0 -5
  125. package/src/surfaces/drawers/drawer_bottom/drawer_bottom.tsx +0 -23
  126. package/src/surfaces/drawers/drawer_end/drawer_end.module.css +0 -5
  127. package/src/surfaces/drawers/drawer_end/drawer_end.tsx +0 -24
  128. package/src/surfaces/drawers/drawer_start/drawer_start.module.css +0 -5
  129. package/src/surfaces/drawers/drawer_start/drawer_start.tsx +0 -23
  130. package/src/surfaces/drawers/drawer_top/drawer_top.module.css +0 -5
  131. package/src/surfaces/drawers/drawer_top/drawer_top.tsx +0 -24
@@ -11,7 +11,7 @@ import { Input } from '../input/input.js';
11
11
  import styles from './color_input.module.css';
12
12
 
13
13
  import { Popper } from '../../overlay/popper/legacy/popper.js';
14
- import { InputGroup } from '../input_group/input_group.js';
14
+ import { ControlSet } from '../control_set/control_set.js';
15
15
 
16
16
  export interface ColorInputProps
17
17
  extends Omit<HTMLAttributes<HTMLButtonElement>, 'onChange' | 'onError'> {
@@ -77,7 +77,7 @@ export function ColorInput({
77
77
 
78
78
  return (
79
79
  <>
80
- <InputGroup
80
+ <ControlSet
81
81
  height="auto"
82
82
  width={width}
83
83
  minWidth={minWidth}
@@ -133,7 +133,7 @@ export function ColorInput({
133
133
  </HStack>
134
134
  <Spacer width="4px" />
135
135
  </Button>
136
- </InputGroup>
136
+ </ControlSet>
137
137
  <Popper
138
138
  anchorElement={anchorElement}
139
139
  onClose={closePicker}
@@ -0,0 +1,158 @@
1
+ import React from 'react';
2
+ import { Control, ControlRow } from './control.js';
3
+ import { Input } from '../input/input.js';
4
+ import { Button } from '../../actions/button/button/button.js';
5
+ import { SearchIcon } from '@tcn/icons/search_icon.js';
6
+ import { CrossIcon } from '@tcn/icons/cross_icon.js';
7
+ import { Textarea } from '../textarea/textarea.js';
8
+ import { BugIcon } from '@tcn/icons/bug_icon.js';
9
+ import { BodyText } from '../../typography/index.js';
10
+ import { Spacer } from '../../stacks/spacer.js';
11
+ import { CopyIcon } from '@tcn/icons/copy_icon.js';
12
+ import { SendOneIcon } from '@tcn/icons/send_one_icon.js';
13
+ import { FilterOneIcon } from '@tcn/icons/filter_one_icon.js';
14
+ import { PlusIcon } from '@tcn/icons/plus_icon.js';
15
+ import styles from './control_stories.module.css';
16
+ import { RefreshCcwAlertIcon } from '@tcn/icons/refresh_ccw_alert_icon.js';
17
+ import { PlayIcon } from '@tcn/icons/play_icon.js';
18
+ import { DatePickerInput } from '../date_picker/date_picker_input.js';
19
+ import { Divider } from '../../layouts/index.js';
20
+ import { CalendarDatesIcon } from '@tcn/icons/calendar_dates_icon.js';
21
+
22
+ export default {
23
+ title: 'Inputs/Control',
24
+ parameters: {
25
+ docs: {
26
+ description: {
27
+ component:
28
+ 'Control and ControlRow layout components for grouping inputs with optional leading/trailing slots (icons, actions).',
29
+ },
30
+ },
31
+ },
32
+ tags: ['autodocs'],
33
+ };
34
+
35
+ function BaseInput(props: React.ComponentProps<typeof Input>) {
36
+ const [value, setValue] = React.useState(props.value ?? '');
37
+ return <Input {...props} value={value} onChange={setValue} />;
38
+ }
39
+
40
+ export function Baseline() {
41
+ return (
42
+ <Control maxWidth={400}>
43
+ <ControlRow>
44
+ <BaseInput placeholder="Enter text..." />
45
+ </ControlRow>
46
+ </Control>
47
+ );
48
+ }
49
+
50
+ export function Icons() {
51
+ return (
52
+ <Control maxWidth={400}>
53
+ <ControlRow>
54
+ <BugIcon />
55
+ <BaseInput placeholder="Search..." />
56
+ <FilterOneIcon />
57
+ <SearchIcon />
58
+ </ControlRow>
59
+ </Control>
60
+ );
61
+ }
62
+
63
+ export function Actions() {
64
+ return (
65
+ <Control maxWidth={400}>
66
+ <ControlRow>
67
+ <Button utility onClick={() => {}} hierarchy="tertiary">
68
+ <PlusIcon />
69
+ </Button>
70
+ <BaseInput placeholder="Type to clear..." value="Hello" />
71
+ <Button utility onClick={() => {}} hierarchy="tertiary">
72
+ <CrossIcon />
73
+ </Button>
74
+ </ControlRow>
75
+ </Control>
76
+ );
77
+ }
78
+
79
+ export function DatePickerControl() {
80
+ const [value, setValue] = React.useState<Date | null>(null);
81
+ return (
82
+ <Control maxWidth={400}>
83
+ <ControlRow>
84
+ <DatePickerInput value={value} onChange={setValue} width="fill" />
85
+ <Button utility onClick={() => {}} hierarchy="tertiary">
86
+ <CrossIcon />
87
+ </Button>
88
+ <Divider vertical length="sm" />
89
+ <CalendarDatesIcon />
90
+ </ControlRow>
91
+ </Control>
92
+ );
93
+ }
94
+
95
+ export function StartRow() {
96
+ return (
97
+ <Control maxWidth={400}>
98
+ <ControlRow>
99
+ <BugIcon />
100
+ <BodyText>script.js</BodyText>
101
+ <Spacer />
102
+ <Button utility onClick={() => {}} hierarchy="tertiary">
103
+ <CopyIcon />
104
+ </Button>
105
+ </ControlRow>
106
+ <ControlRow growWeight={1}>
107
+ <Textarea placeholder="console.log('Hello, world!');" />
108
+ </ControlRow>
109
+ </Control>
110
+ );
111
+ }
112
+
113
+ export function EndRow() {
114
+ return (
115
+ <Control maxWidth={400}>
116
+ <ControlRow growWeight={1}>
117
+ <Textarea rows={6} placeholder="What's on your mind?" />
118
+ </ControlRow>
119
+ <Spacer />
120
+ <ControlRow growWeight={1}>
121
+ <BodyText>{`<n> characters remaining`}</BodyText>
122
+ <Spacer />
123
+ <Button onClick={() => {}} hierarchy="tertiary">
124
+ Post <SendOneIcon />
125
+ </Button>
126
+ </ControlRow>
127
+ </Control>
128
+ );
129
+ }
130
+
131
+ export function CustomStyles() {
132
+ return (
133
+ <Control className={styles.customStyles} maxWidth={400}>
134
+ <ControlRow growWeight={1}>
135
+ <BugIcon />
136
+ <BodyText>script.js</BodyText>
137
+ <Spacer />
138
+ <Button utility onClick={() => {}} hierarchy="tertiary">
139
+ <RefreshCcwAlertIcon />
140
+ </Button>
141
+ <Button utility onClick={() => {}} hierarchy="tertiary">
142
+ <CopyIcon />
143
+ </Button>
144
+ </ControlRow>
145
+ <ControlRow growWeight={1}>
146
+ <Textarea rows={6} placeholder="Enter your code..." />
147
+ </ControlRow>
148
+ <Spacer />
149
+ <ControlRow growWeight={1}>
150
+ <BodyText>{`Line <i> Column <j>`}</BodyText>
151
+ <Spacer />
152
+ <Button onClick={() => {}} hierarchy="tertiary">
153
+ Run <PlayIcon />
154
+ </Button>
155
+ </ControlRow>
156
+ </Control>
157
+ );
158
+ }
@@ -0,0 +1,32 @@
1
+ import { clsx } from 'clsx';
2
+ import React from 'react';
3
+ import { VStack, type VStackProps } from '../../stacks/v_stack.js';
4
+ import { HStack, type HStackProps } from '../../stacks/h_stack.js';
5
+
6
+ export interface ControlProps extends VStackProps {}
7
+
8
+ export const Control = React.forwardRef<HTMLDivElement, ControlProps>(function Control(
9
+ { as = 'div', className, children, ...props }: ControlProps,
10
+ ref: React.Ref<HTMLDivElement>
11
+ ) {
12
+ return (
13
+ <VStack ref={ref} as={as} className={clsx(className, 'tcn-control')} {...props}>
14
+ {children}
15
+ </VStack>
16
+ );
17
+ });
18
+
19
+ export interface ControlRowProps extends HStackProps {}
20
+
21
+ export const ControlRow = React.forwardRef<HTMLDivElement, ControlRowProps>(
22
+ function ControlRow(
23
+ { as = 'div', className, children, ...props }: ControlRowProps,
24
+ ref: React.Ref<HTMLDivElement>
25
+ ) {
26
+ return (
27
+ <HStack ref={ref} as={as} className={clsx(className, 'tcn-control-row')} {...props}>
28
+ {children}
29
+ </HStack>
30
+ );
31
+ }
32
+ );
@@ -0,0 +1,7 @@
1
+ .custom-styles > *:not(:last-child) {
2
+ border-bottom: 1px solid var(--ergo-grey);
3
+ }
4
+
5
+ .custom-styles > :global(.tcn-control-row) {
6
+ min-height: 40px;
7
+ }
@@ -0,0 +1,46 @@
1
+ import { useState } from 'react';
2
+ import { ControlSet } from './control_set.js';
3
+ import { Input } from '../input/input.js';
4
+ import { Select } from '../select/select.js';
5
+ import { Option } from '../options/option.js';
6
+
7
+ export default {
8
+ title: 'Inputs/Control Set',
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component:
13
+ 'Control Sets are used to group controls and/or inputs that manage multiple values that are closely related and must be entered together. Usually a tuple like (value, unit) or (start, end). For example a value + unit input/selection.',
14
+ },
15
+ },
16
+ },
17
+ tags: ['autodocs'],
18
+ };
19
+
20
+ export function Baseline() {
21
+ const [value, setValue] = useState('42');
22
+ const [unit, setUnit] = useState('kg');
23
+
24
+ return (
25
+ <ControlSet maxWidth="200px">
26
+ <Input type="number" value={value} onChange={setValue} placeholder="Value" />
27
+ <Select
28
+ width="auto"
29
+ minWidth="24px"
30
+ value={unit}
31
+ onChange={setUnit}
32
+ placeholder="Unit"
33
+ >
34
+ <Option value="kg" label="kg">
35
+ kg
36
+ </Option>
37
+ <Option value="lb" label="lb">
38
+ lb
39
+ </Option>
40
+ <Option value="g" label="g">
41
+ g
42
+ </Option>
43
+ </Select>
44
+ </ControlSet>
45
+ );
46
+ }
@@ -2,23 +2,23 @@ import React from 'react';
2
2
  import { clsx } from 'clsx';
3
3
  import { HStack, type HStackProps } from '../../stacks/h_stack.js';
4
4
 
5
- export type InputGroupProps = HStackProps;
5
+ export type ControlSetProps = HStackProps;
6
6
 
7
- export const InputGroup = React.forwardRef<HTMLElement, InputGroupProps>(
7
+ export const ControlSet = React.forwardRef<HTMLElement, ControlSetProps>(
8
8
  function InputGroup(
9
- { children, as = 'div', className, ...props }: InputGroupProps,
9
+ { children, as = 'div', className, ...props }: ControlSetProps,
10
10
  ref
11
11
  ) {
12
12
  const clonedChildren = React.Children.map(children, child =>
13
13
  React.isValidElement(child)
14
14
  ? React.cloneElement(child, {
15
15
  ...child.props,
16
- className: clsx(child.props.className, 'tcn-input-group-slot'),
16
+ className: clsx(child.props.className, 'tcn-control-set-item'),
17
17
  })
18
18
  : child
19
19
  );
20
20
  return (
21
- <HStack ref={ref} as={as} className={clsx(className, 'tcn-input-group')} {...props}>
21
+ <HStack ref={ref} as={as} className={clsx(className, 'tcn-control-set')} {...props}>
22
22
  {clonedChildren}
23
23
  </HStack>
24
24
  );
@@ -61,7 +61,7 @@ function DatePickerActions({ presenter }: { presenter: DatePickerPresenter }) {
61
61
  );
62
62
  }
63
63
 
64
- export function DatePickerInput() {
64
+ export function Baseline() {
65
65
  const [value, setValue] = useState<Date | null>(null);
66
66
 
67
67
  return <DatePickerInputComponent value={value} onChange={setValue} width="300px" />;
@@ -125,7 +125,7 @@ export const DatePickerInput = React.forwardRef<HTMLButtonElement, DatePickerInp
125
125
  <>
126
126
  <Button
127
127
  ref={ref}
128
- className={clsx(styles.button, 'tcn-select')}
128
+ className={clsx(styles.button, 'tcn-entry', 'tcn-date-picker-input')}
129
129
  hAlign="start"
130
130
  disabled={disabled}
131
131
  hierarchy={hierarchy}
@@ -55,7 +55,8 @@ export * from './textarea/textarea.js';
55
55
 
56
56
  export * from './unit_input/unit_input.js';
57
57
 
58
- export * from './input_group/input_group.js';
58
+ export * from './control_set/control_set.js';
59
+ export * from './control/control.js';
59
60
 
60
61
  export {
61
62
  SelectGroup,
@@ -22,7 +22,7 @@ export const Input = React.forwardRef(function Input(
22
22
  ) {
23
23
  return (
24
24
  <input
25
- className={clsx(styles.input, className, 'tcn-input', 'tcn-control')}
25
+ className={clsx(styles.input, className, 'tcn-input', 'tcn-entry')}
26
26
  type={type}
27
27
  ref={ref}
28
28
  data-is-disabled={props.disabled || false}
@@ -117,7 +117,7 @@ export function PhoneNumberCountrySelectAdapter({
117
117
  onChange={handleChange}
118
118
  disabled={disabled}
119
119
  aria-label={ariaLabel ?? 'Country'}
120
- className={clsx(className, 'tcn-input-group-slot')}
120
+ className={clsx(className, 'tcn-control-set-item')}
121
121
  width="auto"
122
122
  >
123
123
  {items}
@@ -150,7 +150,7 @@ export function PhoneNumberInput({
150
150
  className={clsx(
151
151
  styles['phone-number-input'],
152
152
  'tcn-phone-number-input',
153
- 'tcn-input-group'
153
+ 'tcn-control-set'
154
154
  )}
155
155
  displayInitialValueAsLocalNumber
156
156
  addInternationalOption={false}
@@ -95,13 +95,13 @@ export const PhoneNumberInputAdapter = forwardRef<
95
95
  ref={forkedRef}
96
96
  value={value}
97
97
  {...(rest as any)}
98
- className={clsx(className, 'tcn-input-group-slot')}
98
+ className={clsx(className, 'tcn-control-set-item')}
99
99
  onChange={handleChange}
100
100
  />
101
101
  {showPhoneBook && (
102
102
  <Button
103
103
  disabled={disabled}
104
- className={clsx('tcn-input-group-slot', 'tcn-phone-number-phone-book')}
104
+ className={clsx('tcn-control-set-item', 'tcn-phone-number-phone-book')}
105
105
  aria-label={ariaPhoneBookButtonLabel}
106
106
  onClick={togglePhoneBook}
107
107
  size="md"
@@ -2,7 +2,7 @@ import React, { useLayoutEffect } from 'react';
2
2
  import { NotebookIcon } from '@tcn/icons/notebook_icon.js';
3
3
  import { Input } from '../input/input.js';
4
4
  import { Button } from '../../actions/index.js';
5
- import { InputGroup } from '../input_group/input_group.js';
5
+ import { ControlSet } from '../control_set/control_set.js';
6
6
  import clsx from 'clsx';
7
7
  import { usePhoneContext } from './phone_number_context.js';
8
8
  import type { CountryCode } from 'libphonenumber-js';
@@ -104,7 +104,7 @@ export function SipInput({
104
104
 
105
105
  return (
106
106
  <>
107
- <InputGroup>
107
+ <ControlSet>
108
108
  <PhoneNumberCountrySelectAdapter
109
109
  value="SIP"
110
110
  onChange={selectCountry}
@@ -124,7 +124,7 @@ export function SipInput({
124
124
  {showPhoneBook && (
125
125
  <Button
126
126
  disabled={disabled}
127
- className={clsx('tcn-input-group-slot', 'tcn-phone-number-phone-book')}
127
+ className={clsx('tcn-control-set-item', 'tcn-phone-number-phone-book')}
128
128
  aria-label={ariaPhoneBookButtonLabel}
129
129
  onClick={togglePhoneBook}
130
130
  size="md"
@@ -132,7 +132,7 @@ export function SipInput({
132
132
  <NotebookIcon size="md" />
133
133
  </Button>
134
134
  )}
135
- </InputGroup>
135
+ </ControlSet>
136
136
  <SuggestionList
137
137
  open={isPhoneBookOpen}
138
138
  anchorElement={phoneBookElement}
@@ -130,7 +130,7 @@ export const Select = React.forwardRef(function Select(
130
130
  <>
131
131
  <Button
132
132
  ref={forkedRef}
133
- className={clsx(className, 'tcn-select', 'tcn-control', styles.select)}
133
+ className={clsx(className, 'tcn-select', 'tcn-entry', styles.select)}
134
134
  width="100%"
135
135
  {...props}
136
136
  hAlign="start"
@@ -20,7 +20,7 @@ export default {
20
20
  tags: ['autodocs'],
21
21
  };
22
22
 
23
- export function Textarea() {
23
+ export function Baseline(props: TextareaProps) {
24
24
  return (
25
25
  <table className={styles.story}>
26
26
  <colgroup>
@@ -20,7 +20,7 @@ export const Textarea = React.forwardRef(function Textarea(
20
20
  return (
21
21
  <textarea
22
22
  style={{ width, height, ...style }}
23
- className={clsx(className, styles.textarea, 'tcn-textarea', 'tcn-control')}
23
+ className={clsx(className, styles.textarea, 'tcn-textarea', 'tcn-entry')}
24
24
  data-is-disabled={props.disabled || false}
25
25
  ref={ref}
26
26
  onChange={e => {
@@ -7,7 +7,7 @@ import { Select } from '../select/select.js';
7
7
  import { OptionProps } from '../options/option.js';
8
8
  import styles from './unit_input.module.css';
9
9
 
10
- import { InputGroup } from '../input_group/input_group.js';
10
+ import { ControlSet } from '../control_set/control_set.js';
11
11
 
12
12
  function getDisplayValue(value: string) {
13
13
  return value
@@ -80,7 +80,7 @@ export const UnitInput = React.forwardRef(function UnitInput(
80
80
  }
81
81
 
82
82
  return (
83
- <InputGroup
83
+ <ControlSet
84
84
  ref={ref}
85
85
  className={clsx(styles['unit-input'], 'tcn-unit-input')}
86
86
  height="auto"
@@ -110,6 +110,6 @@ export const UnitInput = React.forwardRef(function UnitInput(
110
110
  >
111
111
  {children}
112
112
  </Select>
113
- </InputGroup>
113
+ </ControlSet>
114
114
  );
115
115
  });
@@ -21,14 +21,7 @@ export interface FrameOwnProps {
21
21
  resizable?: boolean;
22
22
  }
23
23
 
24
- export type FrameProps = Omit<
25
- BoxProps,
26
- | 'enableResizeOnLeft'
27
- | 'enableResizeOnRight'
28
- | 'enableResizeOnTop'
29
- | 'enableResizeOnBottom'
30
- > &
31
- FrameOwnProps;
24
+ export type FrameProps = BoxProps & FrameOwnProps;
32
25
 
33
26
  export const Frame = React.forwardRef<HTMLElement, FrameProps>(function Frame(
34
27
  {
@@ -38,6 +31,12 @@ export const Frame = React.forwardRef<HTMLElement, FrameProps>(function Frame(
38
31
  veil = false,
39
32
  resizable = true,
40
33
  className,
34
+ enableResizeOnTop = true,
35
+ enableResizeOnBottom = true,
36
+ enableResizeOnStart = true,
37
+ enableResizeOnEnd = true,
38
+ enableResizeOnLeft = false,
39
+ enableResizeOnRight = false,
41
40
  ...rest
42
41
  }: FrameProps,
43
42
  ref
@@ -50,14 +49,12 @@ export const Frame = React.forwardRef<HTMLElement, FrameProps>(function Frame(
50
49
  <FrameDialog
51
50
  className={className}
52
51
  ref={ref}
53
- enableResizeOnLeft={resizable}
54
- enableResizeOnRight={resizable}
55
- enableResizeOnTop={resizable}
56
- enableResizeOnBottom={resizable}
57
- // TODO: check to see if these should be enabled, and if so - if left/right should be disabled.
58
- // Could add a "directional" prop and use that in conjunction with enableResizeOnStart/End and deprecate enableResizeOnLeft/Right.
59
- // enableResizeOnStart={resizable}
60
- // enableResizeOnEnd={resizable}
52
+ enableResizeOnStart={resizable && enableResizeOnStart}
53
+ enableResizeOnEnd={resizable && enableResizeOnEnd}
54
+ enableResizeOnTop={resizable && enableResizeOnTop}
55
+ enableResizeOnBottom={resizable && enableResizeOnBottom}
56
+ enableResizeOnRight={resizable && enableResizeOnRight}
57
+ enableResizeOnLeft={resizable && enableResizeOnLeft}
61
58
  draggable={draggable}
62
59
  {...rest}
63
60
  >
@@ -0,0 +1,30 @@
1
+ @layer tcn-system {
2
+ :where(.slide) {
3
+ position: absolute;
4
+
5
+ &[data-side="top"],
6
+ &[data-side="bottom"] {
7
+ width: 100%;
8
+ }
9
+ &[data-side="start"],
10
+ &[data-side="end"] {
11
+ height: 100%;
12
+ }
13
+ &[data-side="top"] {
14
+ top: 0;
15
+ }
16
+
17
+ &[data-side="bottom"] {
18
+ bottom: 0;
19
+ }
20
+
21
+ /* TODO: support LTR directionality */
22
+ &[data-side="start"] {
23
+ left: 0;
24
+ }
25
+
26
+ &[data-side="end"] {
27
+ right: 0;
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,58 @@
1
+ import { Header, Scaffold, VBody } from '../../layouts/index.js';
2
+ import { ZStack } from '../../stacks/z_stack.js';
3
+ import { BodyText } from '../../typography/index.js';
4
+ import { Title } from '../../typography/title/title.js';
5
+ import { Slide, type SlideProps } from './slide.js';
6
+ import { DragHandle } from '../../utils/dnd/handle.js';
7
+
8
+ export default {
9
+ title: 'Overlays/Floating/Slide',
10
+ component: Slide,
11
+ tags: ['autodocs'],
12
+
13
+ args: {
14
+ isOpen: true,
15
+ veil: false,
16
+ resizable: true,
17
+ side: 'top',
18
+ },
19
+ argTypes: {
20
+ side: {
21
+ control: 'select',
22
+ options: ['top', 'bottom', 'start', 'end'],
23
+ },
24
+ },
25
+ };
26
+
27
+ export const SlideStory = (args: Omit<SlideProps, 'children'>) => {
28
+ const isVertical = args.side === 'top' || args.side === 'bottom';
29
+ return (
30
+ <ZStack height="100%" width="100%" minHeight="600px">
31
+ <Slide
32
+ height={isVertical ? '300px' : undefined}
33
+ width={!isVertical ? '300px' : undefined}
34
+ minHeight={isVertical ? '100px' : undefined}
35
+ minWidth={!isVertical ? '100px' : undefined}
36
+ maxHeight={isVertical ? '90%' : undefined}
37
+ maxWidth={!isVertical ? '90%' : undefined}
38
+ style={{
39
+ background: 'white',
40
+ }}
41
+ {...args}
42
+ >
43
+ <Scaffold>
44
+ <DragHandle>
45
+ <Header>
46
+ <Title> This is a Slide</Title>
47
+ </Header>
48
+ </DragHandle>
49
+ <VBody>
50
+ <BodyText>
51
+ This component is fixed to a side of a container (top, bottom, start, end).
52
+ </BodyText>
53
+ </VBody>
54
+ </Scaffold>
55
+ </Slide>
56
+ </ZStack>
57
+ );
58
+ };
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import { Frame, type FrameProps } from '../frame/frame.js';
3
+ import { clsx } from 'clsx';
4
+
5
+ // Styles
6
+ import styles from './slide.module.css';
7
+
8
+ export type SlideSide = 'top' | 'bottom' | 'start' | 'end';
9
+
10
+ export interface SlideOwnProps {
11
+ side: SlideSide;
12
+ }
13
+
14
+ export type SlideProps = Omit<
15
+ FrameProps,
16
+ | 'draggable'
17
+ | 'enableResizeOnLeft'
18
+ | 'enableResizeOnRight'
19
+ | 'enableResizeOnTop'
20
+ | 'enableResizeOnBottom'
21
+ | 'enableResizeOnStart'
22
+ | 'enableResizeOnEnd'
23
+ > &
24
+ SlideOwnProps;
25
+
26
+ // A Frame fixed to a side of a container (top, bottom, start, end) - disables dragging - and limits resizing to one side
27
+ export const Slide = React.forwardRef<HTMLElement, SlideProps>(function Slide(
28
+ { children, side, resizable = false, className, ...rest },
29
+ ref
30
+ ) {
31
+ const isVertical = side === 'top' || side === 'bottom';
32
+
33
+ return (
34
+ <Frame
35
+ data-side={side}
36
+ className={clsx(styles['slide'], className)}
37
+ draggable={false}
38
+ ref={ref}
39
+ data-is-vertical={isVertical}
40
+ data-is-horizontal={!isVertical}
41
+ resizable={resizable}
42
+ enableResizeOnTop={side === 'bottom'}
43
+ enableResizeOnBottom={side === 'top'}
44
+ enableResizeOnStart={side === 'end'}
45
+ enableResizeOnEnd={side === 'start'}
46
+ {...rest}
47
+ >
48
+ {children}
49
+ </Frame>
50
+ );
51
+ });
@@ -0,0 +1,5 @@
1
+ @layer tcn-system {
2
+ .aside {
3
+ height: 100%;
4
+ }
5
+ }