teachable-design-system 0.2.1 → 0.3.2

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 (50) hide show
  1. package/dist/index.cjs.js +875 -64
  2. package/dist/index.cjs.js.map +1 -1
  3. package/dist/index.d.ts +72 -2
  4. package/dist/index.esm.js +877 -67
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/types/components/Dropdown/Dropdown.d.ts +1 -1
  7. package/dist/types/components/Dropdown/Dropdown.d.ts.map +1 -1
  8. package/dist/types/components/Dropdown/style.d.ts +1 -0
  9. package/dist/types/components/Dropdown/style.d.ts.map +1 -1
  10. package/dist/types/components/Table/Table.d.ts +3 -0
  11. package/dist/types/components/Table/Table.d.ts.map +1 -0
  12. package/dist/types/components/Table/index.d.ts +3 -0
  13. package/dist/types/components/Table/index.d.ts.map +1 -0
  14. package/dist/types/components/Table/style.d.ts +98 -0
  15. package/dist/types/components/Table/style.d.ts.map +1 -0
  16. package/dist/types/components/Table/table-body.d.ts +3 -0
  17. package/dist/types/components/Table/table-body.d.ts.map +1 -0
  18. package/dist/types/components/Table/table-cell.d.ts +3 -0
  19. package/dist/types/components/Table/table-cell.d.ts.map +1 -0
  20. package/dist/types/components/Table/table-header.d.ts +4 -0
  21. package/dist/types/components/Table/table-header.d.ts.map +1 -0
  22. package/dist/types/components/index.d.ts +1 -0
  23. package/dist/types/components/index.d.ts.map +1 -1
  24. package/dist/types/types/Dropdown.types.d.ts +1 -0
  25. package/dist/types/types/Dropdown.types.d.ts.map +1 -1
  26. package/dist/types/types/index.d.ts +6 -0
  27. package/dist/types/types/index.d.ts.map +1 -1
  28. package/dist/types/types/table.d.ts +141 -0
  29. package/dist/types/types/table.d.ts.map +1 -0
  30. package/package.json +1 -1
  31. package/src/components/Dropdown/Dropdown.stories.tsx +4 -0
  32. package/src/components/Dropdown/Dropdown.tsx +2 -1
  33. package/src/components/Dropdown/style.ts +2 -1
  34. package/src/components/Sidebar/style.ts +4 -4
  35. package/src/components/Table/Table.stories.tsx +179 -0
  36. package/src/components/Table/Table.tsx +510 -0
  37. package/src/components/Table/index.ts +2 -0
  38. package/src/components/Table/style.ts +345 -0
  39. package/src/components/Table/table-body.tsx +112 -0
  40. package/src/components/Table/table-cell.tsx +153 -0
  41. package/src/components/Table/table-header.tsx +52 -0
  42. package/src/components/index.ts +5 -4
  43. package/src/types/Dropdown.types.ts +1 -0
  44. package/src/types/index.ts +6 -0
  45. package/src/types/table.ts +150 -0
  46. package/dist/assets/icons/arrow-down.png +0 -0
  47. package/dist/assets/icons/checked.png +0 -0
  48. package/dist/assets/icons/icon_size.png +0 -0
  49. package/dist/assets/images/.gitkeep +0 -0
  50. package/dist/assets/index.ts +0 -1
@@ -1,3 +1,3 @@
1
1
  import { DropdownProps } from "../../types/Dropdown.types";
2
- export declare function Dropdown({ size, options, onSelect, label, placeholder }: DropdownProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function Dropdown({ size, options, onSelect, label, placeholder, width }: DropdownProps): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=Dropdown.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../../../../src/components/Dropdown/Dropdown.tsx"],"names":[],"mappings":"AACA,OAAO,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAIzD,wBAAgB,QAAQ,CAAC,EAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAC,EAAE,aAAa,2CAkDpF"}
1
+ {"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../../../../src/components/Dropdown/Dropdown.tsx"],"names":[],"mappings":"AACA,OAAO,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAIzD,wBAAgB,QAAQ,CAAC,EAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAC,EAAE,aAAa,2CAmD3F"}
@@ -3,6 +3,7 @@ export interface StyledDropdownProps {
3
3
  onSelect?: (option: string) => void;
4
4
  isOpen?: boolean;
5
5
  isSelected?: boolean;
6
+ width?: string;
6
7
  }
7
8
  export declare const StyledDropDown: import("@emotion/styled").StyledComponent<{
8
9
  theme?: import("@emotion/react").Theme;
@@ -1 +1 @@
1
- {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../../../src/components/Dropdown/style.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,mBAAmB;IACnC,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AA+FD,eAAO,MAAM,cAAc;;;2IAc1B,CAAC;AAEF,eAAO,MAAM,SAAS;;;yGAOrB,CAAA;AAED,eAAO,MAAM,UAAU;;;2IAStB,CAAA;AAED,eAAO,MAAM,WAAW;;;qHAGvB,CAAA;AAED,eAAO,MAAM,UAAU;;;+HAEtB,CAAA;AAED,eAAO,MAAM,aAAa;;;+HAezB,CAAA;AAED,eAAO,MAAM,YAAY;;;+HA4CxB,CAAA"}
1
+ {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../../../src/components/Dropdown/style.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,mBAAmB;IACnC,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AA+FD,eAAO,MAAM,cAAc;;;2IAc1B,CAAC;AAEF,eAAO,MAAM,SAAS;;;yGAOrB,CAAA;AAED,eAAO,MAAM,UAAU;;;2IAStB,CAAA;AAED,eAAO,MAAM,WAAW;;;qHAGvB,CAAA;AAED,eAAO,MAAM,UAAU;;;+HAEtB,CAAA;AAED,eAAO,MAAM,aAAa;;;+HAezB,CAAA;AAED,eAAO,MAAM,YAAY;;;+HA4CxB,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { TableProps } from '../../types/table';
2
+ export default function Table<T extends Record<string, unknown> = Record<string, unknown>>({ columns, data, onCellEdit, onSort, onSelectionChange, onPaste, maxHeight, rowHeight, className, enableRowSelection, selectedRowIndex, onRowClick, enableKeyboardNavigation, }: TableProps<T>): import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=Table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/Table.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAyC,MAAM,mBAAmB,CAAC;AAoD3F,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EACzF,OAAO,EACP,IAAI,EACJ,UAAU,EACV,MAAM,EACN,iBAAiB,EACjB,OAAO,EACP,SAAS,EACT,SAAS,EACT,SAAS,EACT,kBAAkB,EAClB,gBAAgB,EAChB,UAAU,EACV,wBAAwB,GACzB,EAAE,UAAU,CAAC,CAAC,CAAC,2CAybf"}
@@ -0,0 +1,3 @@
1
+ export { default } from './Table';
2
+ export { default as Table } from './Table';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,98 @@
1
+ import type { SortDirection } from '../../types/table';
2
+ export declare const TableOuterWrapper: import("@emotion/styled").StyledComponent<{
3
+ theme?: import("@emotion/react").Theme;
4
+ as?: React.ElementType;
5
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
6
+ export declare const TableWrapper: import("@emotion/styled").StyledComponent<{
7
+ theme?: import("@emotion/react").Theme;
8
+ as?: React.ElementType;
9
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
10
+ export declare const TableContainer: import("@emotion/styled").StyledComponent<{
11
+ theme?: import("@emotion/react").Theme;
12
+ as?: React.ElementType;
13
+ } & {
14
+ maxHeight?: string;
15
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
16
+ export declare const StyledTable: import("@emotion/styled").StyledComponent<{
17
+ theme?: import("@emotion/react").Theme;
18
+ as?: React.ElementType;
19
+ }, import("react").DetailedHTMLProps<import("react").TableHTMLAttributes<HTMLTableElement>, HTMLTableElement>, {}>;
20
+ export declare const TableHead: import("@emotion/styled").StyledComponent<{
21
+ theme?: import("@emotion/react").Theme;
22
+ as?: React.ElementType;
23
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, {}>;
24
+ export declare const TableBody: import("@emotion/styled").StyledComponent<{
25
+ theme?: import("@emotion/react").Theme;
26
+ as?: React.ElementType;
27
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, {}>;
28
+ export declare const TableRow: import("@emotion/styled").StyledComponent<{
29
+ theme?: import("@emotion/react").Theme;
30
+ as?: React.ElementType;
31
+ } & {
32
+ striped?: boolean;
33
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLTableRowElement>, HTMLTableRowElement>, {}>;
34
+ export declare const TableHeaderCell: import("@emotion/styled").StyledComponent<{
35
+ theme?: import("@emotion/react").Theme;
36
+ as?: React.ElementType;
37
+ } & {
38
+ width?: string;
39
+ sortable?: boolean;
40
+ }, import("react").DetailedHTMLProps<import("react").ThHTMLAttributes<HTMLTableHeaderCellElement>, HTMLTableHeaderCellElement>, {}>;
41
+ export declare const TableDataCell: import("@emotion/styled").StyledComponent<{
42
+ theme?: import("@emotion/react").Theme;
43
+ as?: React.ElementType;
44
+ } & {
45
+ editable?: boolean;
46
+ width?: string;
47
+ height?: string;
48
+ isHeaderColumn?: boolean;
49
+ isSelected?: boolean;
50
+ $edgeTop?: boolean;
51
+ $edgeBottom?: boolean;
52
+ $edgeLeft?: boolean;
53
+ $edgeRight?: boolean;
54
+ $rowSelected?: boolean;
55
+ }, import("react").DetailedHTMLProps<import("react").TdHTMLAttributes<HTMLTableDataCellElement>, HTMLTableDataCellElement>, {}>;
56
+ export declare const SortIcon: import("@emotion/styled").StyledComponent<{
57
+ theme?: import("@emotion/react").Theme;
58
+ as?: React.ElementType;
59
+ } & {
60
+ active?: boolean;
61
+ direction?: SortDirection;
62
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {}>;
63
+ export declare const EditableInput: import("@emotion/styled").StyledComponent<{
64
+ theme?: import("@emotion/react").Theme;
65
+ as?: React.ElementType;
66
+ }, import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, {}>;
67
+ export declare const ScrollContainer: import("@emotion/styled").StyledComponent<{
68
+ theme?: import("@emotion/react").Theme;
69
+ as?: React.ElementType;
70
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
71
+ export declare const ScrollButton: import("@emotion/styled").StyledComponent<{
72
+ theme?: import("@emotion/react").Theme;
73
+ as?: React.ElementType;
74
+ } & {
75
+ position: "top" | "bottom";
76
+ }, import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {}>;
77
+ export declare const ContextMenuOverlay: import("@emotion/styled").StyledComponent<{
78
+ theme?: import("@emotion/react").Theme;
79
+ as?: React.ElementType;
80
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
81
+ export declare const ContextMenu: import("@emotion/styled").StyledComponent<{
82
+ theme?: import("@emotion/react").Theme;
83
+ as?: React.ElementType;
84
+ } & {
85
+ x: number;
86
+ y: number;
87
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
88
+ export declare const ContextMenuItem: import("@emotion/styled").StyledComponent<{
89
+ theme?: import("@emotion/react").Theme;
90
+ as?: React.ElementType;
91
+ } & {
92
+ disabled?: boolean;
93
+ }, import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {}>;
94
+ export declare const ContextMenuDivider: import("@emotion/styled").StyledComponent<{
95
+ theme?: import("@emotion/react").Theme;
96
+ as?: React.ElementType;
97
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
98
+ //# sourceMappingURL=style.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/style.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA6BvD,eAAO,MAAM,iBAAiB;;;yGAQ7B,CAAC;AAEF,eAAO,MAAM,YAAY;;;yGAKxB,CAAC;AAEF,eAAO,MAAM,cAAc;;;;gBAA4B,MAAM;yGAuC5D,CAAC;AAKF,eAAO,MAAM,WAAW;;;kHAMvB,CAAC;AAEF,eAAO,MAAM,SAAS;;;2HAKrB,CAAC;AAEF,eAAO,MAAM,SAAS;;;2HAAiB,CAAC;AAExC,eAAO,MAAM,QAAQ;;;;cAAyB,OAAO;mHAQpD,CAAC;AAWF,eAAO,MAAM,eAAe;;;;YAAuB,MAAM;eAAa,OAAO;mIA8B5E,CAAC;AAEF,eAAO,MAAM,aAAa;;;;eACb,OAAO;YACV,MAAM;aACL,MAAM;qBACE,OAAO;iBACX,OAAO;eACT,OAAO;kBACJ,OAAO;gBACT,OAAO;iBACN,OAAO;mBACL,OAAO;+HAiDvB,CAAC;AAKF,eAAO,MAAM,QAAQ;;;;aAA0B,OAAO;gBAAc,aAAa;2GAUhF,CAAC;AAEF,eAAO,MAAM,aAAa;;;kHAazB,CAAC;AAKF,eAAO,MAAM,eAAe;;;yGAM3B,CAAC;AAEF,eAAO,MAAM,YAAY;;;;cAA6B,KAAK,GAAG,QAAQ;qHA0BrE,CAAC;AAKF,eAAO,MAAM,kBAAkB;;;yGAO9B,CAAC;AAEF,eAAO,MAAM,WAAW;;;;OAAmB,MAAM;OAAK,MAAM;yGAY3D,CAAC;AAEF,eAAO,MAAM,eAAe;;;;eAA8B,OAAO;qHAsBhE,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;yGAI9B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { TableBodyProps } from '../../types/table';
2
+ export default function TableBody<T extends Record<string, unknown> = Record<string, unknown>>({ columns, data, rowHeight, onCellEdit, selectionStart, selectionEnd, editingCell, editStartValue, editToken, onCellMouseDown, onCellMouseEnter, onCellMouseUp, enableRowSelection, selectedRowIndex, hoveredRowIndex, onRowClick, onRowHover, }: TableBodyProps<T>): import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=table-body.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-body.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/table-body.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,mBAAmB,CAAC;AAoCtE,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC7F,OAAO,EACP,IAAI,EACJ,SAAS,EACT,UAAU,EACV,cAAc,EACd,YAAY,EACZ,WAAW,EACX,cAAc,EACd,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,UAAU,GACX,EAAE,cAAc,CAAC,CAAC,CAAC,2CAwDnB"}
@@ -0,0 +1,3 @@
1
+ import type { TableCellProps } from '../../types/table';
2
+ export default function TableCell({ value, editable, width, height, rowHeight, dataType, isHeaderColumn, isSelected, rowSelected, isEditingRequested, startEditingToken, startEditingValue, selectionEdge, rowSpan, colSpan, onEdit, render, onMouseDown, onMouseEnter, onMouseUp, }: TableCellProps): import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=table-cell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-cell.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/table-cell.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAY,MAAM,mBAAmB,CAAC;AAuClE,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,KAAK,EACL,QAAgB,EAChB,KAAK,EACL,MAAM,EACN,SAAS,EACT,QAAiB,EACjB,cAAsB,EACtB,UAAkB,EAClB,WAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,OAAO,EACP,OAAO,EACP,MAAM,EACN,MAAM,EACN,WAAW,EACX,YAAY,EACZ,SAAS,GACV,EAAE,cAAc,2CA2FhB"}
@@ -0,0 +1,4 @@
1
+ import type { TableHeaderProps } from '../../types/table';
2
+ /** 테이블 헤더 */
3
+ export default function TableHeader<T = Record<string, unknown>>({ columns, sortColumn, sortDirection, onSort, }: TableHeaderProps<T>): import("react/jsx-runtime").JSX.Element;
4
+ //# sourceMappingURL=table-header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-header.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/table-header.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,mBAAmB,CAAC;AAWzE,aAAa;AACb,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/D,OAAO,EACP,UAAU,EACV,aAAa,EACb,MAAM,GACP,EAAE,gBAAgB,CAAC,CAAC,CAAC,2CAgCrB"}
@@ -4,4 +4,5 @@ export * from './Dropdown';
4
4
  export * from './Input';
5
5
  export * from './Sidebar';
6
6
  export * from './TabBar';
7
+ export * from './Table';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
@@ -4,5 +4,6 @@ export interface DropdownProps {
4
4
  options: string[];
5
5
  label?: string;
6
6
  placeholder?: string;
7
+ width?: string;
7
8
  }
8
9
  //# sourceMappingURL=Dropdown.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.types.d.ts","sourceRoot":"","sources":["../../../src/types/Dropdown.types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC7B,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB"}
1
+ {"version":3,"file":"Dropdown.types.d.ts","sourceRoot":"","sources":["../../../src/types/Dropdown.types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC7B,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf"}
@@ -1 +1,7 @@
1
+ export * from './button.types';
2
+ export * from './checkBox.types';
3
+ export * from './Dropdown.types';
4
+ export * from './input.types';
5
+ export * from './Sidebar.types';
6
+ export * from './table';
1
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC"}
@@ -0,0 +1,141 @@
1
+ import type { ReactNode } from 'react';
2
+ /** 셀 데이터 타입 */
3
+ export type DataType = 'text' | 'number' | 'date' | 'boolean' | 'custom';
4
+ /** 정렬 방향 */
5
+ export type SortDirection = 'asc' | 'desc' | null;
6
+ /**
7
+ * 테이블 컬럼 정의
8
+ * @template T - 행 데이터 타입
9
+ */
10
+ export interface TableColumn<T = Record<string, unknown>> {
11
+ /** 컬럼 고유 키 */
12
+ key: keyof T extends string ? keyof T : string;
13
+ /** 헤더 텍스트 */
14
+ header: string;
15
+ /** 컬럼 너비 (예: '100px', '20%') */
16
+ width?: string;
17
+ /** 편집 가능 여부 @default true */
18
+ editable?: boolean;
19
+ /** 셀 높이 */
20
+ height?: string;
21
+ /** 데이터 타입 @default 'text' */
22
+ dataType?: DataType;
23
+ /** 정렬 가능 여부 @default false */
24
+ sortable?: boolean;
25
+ /** 헤더 스타일 적용 (좌측 열 강조) */
26
+ isHeaderColumn?: boolean;
27
+ /** 행 병합 수 */
28
+ rowSpan?: number;
29
+ /** 열 병합 수 */
30
+ colSpan?: number;
31
+ /** 커스텀 렌더링 */
32
+ render?: (value: unknown, row: T, rowIndex: number) => ReactNode;
33
+ /** 커스텀 정렬 함수 */
34
+ sortFn?: (a: unknown, b: unknown) => number;
35
+ }
36
+ /** 테이블 행 데이터 타입 */
37
+ export type TableRow<T = Record<string, unknown>> = T;
38
+ /** 테이블 컴포넌트 Props */
39
+ export interface TableProps<T = Record<string, unknown>> {
40
+ columns: TableColumn<T>[];
41
+ data: TableRow<T>[];
42
+ onCellEdit?: (rowIndex: number, columnKey: string, value: unknown) => void;
43
+ onSort?: (columnKey: string, direction: SortDirection) => void;
44
+ onSelectionChange?: (cells: CellPosition[]) => void;
45
+ onPaste?: (startRow: number, startCol: number, values: string[][]) => void;
46
+ /** 최대 높이 (스크롤 활성화) */
47
+ maxHeight?: string;
48
+ /** 행 높이 (기본값: 30px) */
49
+ rowHeight?: string;
50
+ /** 줄무늬 스타일 */
51
+ striped?: boolean;
52
+ className?: string;
53
+ /** 행 선택 활성화 */
54
+ enableRowSelection?: boolean;
55
+ /** 선택된 행 인덱스 */
56
+ selectedRowIndex?: number;
57
+ /** 행 클릭 콜백 */
58
+ onRowClick?: (rowIndex: number, row: T) => void;
59
+ /** 키보드 네비게이션 활성화 (↑↓ 화살표) */
60
+ enableKeyboardNavigation?: boolean;
61
+ }
62
+ /** 테이블 셀 Props */
63
+ export interface TableCellProps {
64
+ value: unknown;
65
+ editable?: boolean;
66
+ width?: string;
67
+ height?: string;
68
+ rowHeight?: string;
69
+ dataType?: DataType;
70
+ isHeaderColumn?: boolean;
71
+ rowSpan?: number;
72
+ colSpan?: number;
73
+ isSelected?: boolean;
74
+ rowSelected?: boolean;
75
+ /** 부모에서 편집 시작 요청 여부 */
76
+ isEditingRequested?: boolean;
77
+ /** 편집 시작 트리거 토큰(값이 바뀌면 편집 시작) */
78
+ startEditingToken?: number;
79
+ /** 편집 시작 시 초기 입력 값(타이핑 시작 등) */
80
+ startEditingValue?: string | null;
81
+ selectionEdge?: {
82
+ top: boolean;
83
+ bottom: boolean;
84
+ left: boolean;
85
+ right: boolean;
86
+ };
87
+ onEdit?: (value: unknown) => void;
88
+ render?: (value: unknown) => ReactNode;
89
+ onMouseDown?: () => void;
90
+ onMouseEnter?: () => void;
91
+ onMouseUp?: () => void;
92
+ }
93
+ /** 테이블 헤더 Props */
94
+ export interface TableHeaderProps<T = Record<string, unknown>> {
95
+ columns: TableColumn<T>[];
96
+ sortColumn?: string;
97
+ sortDirection?: SortDirection;
98
+ onSort?: (columnKey: string) => void;
99
+ }
100
+ /** 테이블 바디 Props */
101
+ export interface TableBodyProps<T = Record<string, unknown>> {
102
+ columns: TableColumn<T>[];
103
+ data: TableRow<T>[];
104
+ rowHeight?: string;
105
+ onCellEdit?: (rowIndex: number, columnKey: string, value: unknown) => void;
106
+ selectedCells?: Set<string>;
107
+ selectionStart?: CellPosition | null;
108
+ selectionEnd?: CellPosition | null;
109
+ /** 키 입력 등으로 시작되는 편집 대상 셀 */
110
+ editingCell?: CellPosition | null;
111
+ /** 키 입력으로 시작된 경우 초기 값 */
112
+ editStartValue?: string | null;
113
+ /** 편집 시작 트리거 토큰 */
114
+ editToken?: number;
115
+ onCellMouseDown?: (rowIndex: number, colIndex: number) => void;
116
+ onCellMouseEnter?: (rowIndex: number, colIndex: number) => void;
117
+ onCellMouseUp?: () => void;
118
+ /** 행 선택 활성화 */
119
+ enableRowSelection?: boolean;
120
+ /** 선택된 행 인덱스 */
121
+ selectedRowIndex?: number;
122
+ /** 호버된 행 인덱스 */
123
+ hoveredRowIndex?: number;
124
+ /** 행 클릭 콜백 */
125
+ onRowClick?: (rowIndex: number) => void;
126
+ /** 행 호버 콜백 */
127
+ onRowHover?: (rowIndex: number | null) => void;
128
+ }
129
+ /** 셀 위치 */
130
+ export interface CellPosition {
131
+ row: number;
132
+ col: number;
133
+ }
134
+ /** 선택 범위 */
135
+ export interface SelectionRange {
136
+ startRow: number;
137
+ endRow: number;
138
+ startCol: number;
139
+ endCol: number;
140
+ }
141
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/types/table.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teachable-design-system",
3
- "version": "0.2.1",
3
+ "version": "0.3.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs.js",
6
6
  "module": "./dist/index.esm.js",
@@ -21,6 +21,10 @@ const meta = {
21
21
  control: 'text',
22
22
  description: '상단 라벨 텍스트',
23
23
  },
24
+ width: {
25
+ control: 'text',
26
+ description: '드롭다운 너비 (예: 320px, 100%)',
27
+ },
24
28
  options: {
25
29
  control: 'object',
26
30
  description: '표시할 옵션 문자열 배열',
@@ -3,7 +3,7 @@ import {DropdownProps} from "../../types/Dropdown.types";
3
3
  import {StyledBox, StyledDropDown, StyledText, StyledLabel, StyledIcon, StyledOptions, StyledOption} from "./style";
4
4
  import arrowDownIcon from '../../assets/icons/arrow-down.png';
5
5
 
6
- export function Dropdown({size, options, onSelect, label, placeholder}: DropdownProps) {
6
+ export function Dropdown({size, options, onSelect, label, placeholder, width}: DropdownProps) {
7
7
  const [open, setOpen] = React.useState(false);
8
8
  const [selected, setSelected] = React.useState<string | null>(null);
9
9
  const ref = React.useRef<HTMLDivElement>(null);
@@ -30,6 +30,7 @@ export function Dropdown({size, options, onSelect, label, placeholder}: Dropdown
30
30
  <StyledLabel>{label}</StyledLabel>
31
31
  <StyledDropDown onClick={() => setOpen((prev) => !prev)}
32
32
  size={size}
33
+ width={width}
33
34
  isOpen={open}
34
35
  >
35
36
  <StyledBox>
@@ -9,6 +9,7 @@ export interface StyledDropdownProps {
9
9
  onSelect?: (option: string) => void;
10
10
  isOpen?: boolean;
11
11
  isSelected?: boolean;
12
+ width?: string;
12
13
  }
13
14
 
14
15
  const getButtonSize = (size?: 'small' | 'medium' | 'large') => {
@@ -112,7 +113,7 @@ export const StyledDropDown = styled.button<StyledDropdownProps>`
112
113
  flex-direction: column;
113
114
  align-items: flex-start;
114
115
  gap: 8px;
115
- width: 320px;
116
+ width: ${({ width }) => width || '320px'};
116
117
 
117
118
  border: ${({ isOpen }) =>
118
119
  isOpen ? `2px solid ${colors.input['border-active']}` : `1px solid ${colors.input.border}`};
@@ -16,8 +16,8 @@ export const StyledIcon = styled.img<TitleProps>`
16
16
 
17
17
  export const StyledSidebar = styled.div`
18
18
  display: flex;
19
- width: 240px;
20
- height: 100vh;
19
+ width: 208px;
20
+ height: 621px;
21
21
  padding: 16px;
22
22
  flex-direction: column;
23
23
  align-items: flex-start;
@@ -33,7 +33,7 @@ export const StyledDescription = styled.div`
33
33
  align-items: flex-start;
34
34
  gap: 18px;
35
35
  flex: 1 0 0;
36
- max-height: calc(100vh - 40px);
36
+ max-height: calc(100% - 40px);
37
37
  overflow-y: auto;
38
38
  overflow-x: hidden;
39
39
 
@@ -89,7 +89,7 @@ export const StyledOpenContents = styled.div`
89
89
  align-items: flex-start;
90
90
  gap: 8px;
91
91
  align-self: stretch;
92
- width: 186px;
92
+ width: 154px;
93
93
 
94
94
  border-radius: 12px;
95
95
  background: ${colors.surface["gray-subtler"]};
@@ -0,0 +1,179 @@
1
+ import React,{ useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import Table from './Table';
4
+ import type { TableColumn } from '../../types/table';
5
+
6
+ const meta = {
7
+ title: 'Components/Table',
8
+ component: Table,
9
+ parameters: { layout: 'padded' },
10
+ tags: ['autodocs'],
11
+ } satisfies Meta<typeof Table>;
12
+
13
+ export default meta;
14
+ type Story = StoryObj<typeof meta>;
15
+
16
+ export const Default: Story = {
17
+ args: {
18
+ columns: [
19
+ { key: 'id', header: 'ID', width: '60px' },
20
+ { key: 'name', header: '이름', width: '120px' },
21
+ ],
22
+ data: [
23
+ { id: 1, name: '홍길동' },
24
+ { id: 2, name: '김철수' },
25
+ ],
26
+ },
27
+ };
28
+
29
+ interface FileData extends Record<string, unknown> {
30
+ no: string;
31
+ filename: string;
32
+ modifiedDate: string;
33
+ school: string;
34
+ classCount: string;
35
+ teacherCount: string;
36
+ }
37
+
38
+ const FileSelectComponent = () => {
39
+ const [selectedRow, setSelectedRow] = useState<number>(0);
40
+
41
+ const columns: TableColumn<FileData>[] = [
42
+ { key: 'no', header: '번호', width: '80px' },
43
+ { key: 'filename', header: '파일명', width: '300px' },
44
+ { key: 'modifiedDate', header: '변경일자', width: '140px' },
45
+ { key: 'school', header: '학교명', width: '250px' },
46
+ { key: 'classCount', header: '학급', width: '80px' },
47
+ { key: 'teacherCount', header: '교사', width: '80px' },
48
+ ];
49
+
50
+ const data: FileData[] = [
51
+ { no: '01', filename: '2025학년도 2학기 시간표(실습)', modifiedDate: '2025-11-05', school: '대구소프트웨어마이스터고', classCount: '12', teacherCount: '0' },
52
+ { no: '02', filename: '2025학년도 2학기 시간표(실습)', modifiedDate: '2025-11-05', school: '대구소프트웨어마이스터고', classCount: '12', teacherCount: '0' },
53
+ { no: '03', filename: '2025학년도 2학기 시간표(실습)', modifiedDate: '2025-11-05', school: '대구소프트웨어마이스터고', classCount: '12', teacherCount: '0' },
54
+ { no: '04', filename: '2025학년도 2학기 시간표(실습)', modifiedDate: '2025-11-05', school: '대구소프트웨어마이스터고', classCount: '12', teacherCount: '0' },
55
+ { no: '05', filename: '2025학년도 2학기 시간표(실습)', modifiedDate: '2025-11-05', school: '대구소프트웨어마이스터고', classCount: '12', teacherCount: '0' },
56
+ { no: '06', filename: '2025학년도 2학기 시간표(실습)', modifiedDate: '2025-11-05', school: '대구소프트웨어마이스터고', classCount: '12', teacherCount: '0' },
57
+ { no: '07', filename: '2025학년도 2학기 시간표(실습)', modifiedDate: '2025-11-05', school: '대구소프트웨어마이스터고', classCount: '12', teacherCount: '0' },
58
+ { no: '08', filename: '2025학년도 2학기 시간표(실습)', modifiedDate: '2025-11-05', school: '대구소프트웨어마이스터고', classCount: '12', teacherCount: '0' },
59
+ { no: '09', filename: '2025학년도 2학기 시간표(실습)', modifiedDate: '2025-11-05', school: '대구소프트웨어마이스터고', classCount: '12', teacherCount: '0' },
60
+ { no: '10', filename: '2025학년도 2학기 시간표(실습)', modifiedDate: '2025-11-05', school: '대구소프트웨어마이스터고', classCount: '12', teacherCount: '0' },
61
+ ];
62
+
63
+ return (
64
+ <div style={{ width: '716px' }}>
65
+ <Table<FileData>
66
+ columns={columns}
67
+ data={data}
68
+ enableRowSelection
69
+ enableKeyboardNavigation
70
+ selectedRowIndex={selectedRow}
71
+ onRowClick={(rowIndex) => setSelectedRow(rowIndex)}
72
+ />
73
+ </div>
74
+ );
75
+ };
76
+
77
+ export const FileSelect: Story = {
78
+ name: 'File Select',
79
+ args: { columns: [], data: [] },
80
+ render: () => <FileSelectComponent />,
81
+ };
82
+
83
+ interface MemberData extends Record<string, unknown> {
84
+ code: string;
85
+ teacher: string;
86
+ }
87
+
88
+ const MemberListComponent = () => {
89
+ const [selectedRow, setSelectedRow] = useState<number>(0);
90
+
91
+ const columns: TableColumn<MemberData>[] = [
92
+ { key: 'code', header: '코드', width: '80px' },
93
+ { key: 'teacher', header: '교사', width: '80px' },
94
+ ];
95
+
96
+ const data: MemberData[] = [
97
+ { code: '01', teacher: '강원석' },
98
+ { code: '02', teacher: '권헌춘' },
99
+ { code: '03', teacher: '김돈호' },
100
+ { code: '04', teacher: '김상숙' },
101
+ { code: '05', teacher: '김영아' },
102
+ { code: '06', teacher: '김익현' },
103
+ { code: '07', teacher: '김인숙' },
104
+ { code: '08', teacher: '김지영' },
105
+ { code: '09', teacher: '김지운' },
106
+ { code: '10', teacher: '류주혜' },
107
+ { code: '11', teacher: '마아람' },
108
+ { code: '12', teacher: '김인숙' },
109
+ { code: '13', teacher: '김지영' },
110
+ { code: '14', teacher: '김지운' },
111
+ { code: '15', teacher: '류주혜' },
112
+ { code: '16', teacher: '마아람' },
113
+ { code: '17', teacher: '마아람' },
114
+ { code: '18', teacher: '마아람' },
115
+ { code: '19', teacher: '마아람' },
116
+ ];
117
+
118
+ return (
119
+ <div style={{ width: '180px' }}>
120
+ <Table<MemberData>
121
+ columns={columns}
122
+ data={data}
123
+ enableRowSelection
124
+ enableKeyboardNavigation
125
+ selectedRowIndex={selectedRow}
126
+ onRowClick={(rowIndex) => setSelectedRow(rowIndex)}
127
+ maxHeight="570px"
128
+ />
129
+ </div>
130
+ );
131
+ };
132
+
133
+ export const MemberList: Story = {
134
+ name: 'Member List',
135
+ args: { columns: [], data: [] },
136
+ render: () => <MemberListComponent />,
137
+ };
138
+
139
+ interface EditRow extends Record<string, unknown> {
140
+ id: number;
141
+ name: string;
142
+ score: number;
143
+ }
144
+
145
+ const EditTableComponent = () => {
146
+ const [data, setData] = useState<EditRow[]>([
147
+ { id: 1, name: '홍길동', score: 90 },
148
+ { id: 2, name: '김철수', score: 75 },
149
+ { id: 3, name: '이영희', score: 88 },
150
+ ]);
151
+
152
+ const columns: TableColumn<EditRow>[] = [
153
+ { key: 'id', header: 'ID', width: '60px', editable: false, dataType: 'number' },
154
+ { key: 'name', header: '이름', width: '140px' },
155
+ { key: 'score', header: '점수', width: '100px', dataType: 'number' },
156
+ ];
157
+
158
+ return (
159
+ <div style={{ width: '320px' }}>
160
+ <Table<EditRow>
161
+ columns={columns}
162
+ data={data}
163
+ onCellEdit={(rowIndex, columnKey, value) => {
164
+ setData((prev) =>
165
+ prev.map((row, idx) =>
166
+ idx === rowIndex ? ({ ...row, [columnKey]: value } as EditRow) : row
167
+ )
168
+ );
169
+ }}
170
+ />
171
+ </div>
172
+ );
173
+ };
174
+
175
+ export const Edit: Story = {
176
+ name: 'Edit',
177
+ args: { columns: [], data: [] },
178
+ render: () => <EditTableComponent />,
179
+ };