@designa8/vibedesign-stripe-deepseek-2-176b 0.1.1 → 0.2.0

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @designa8/vibedesign-stripe-deepseek-2-176b
2
2
 
3
- Complete design system generated by Atoms Design, version **0.1.1**.
3
+ Complete design system generated by Atoms Design, version **0.2.0**.
4
4
  Tokens, atoms, molecules, organisms, and templates — import from the package root;
5
5
  never hardcode visual values in consumer code.
6
6
 
package/dist/styles.css CHANGED
@@ -19,7 +19,6 @@
19
19
  --container-3xl: 48rem;
20
20
  --container-4xl: 56rem;
21
21
  --container-5xl: 64rem;
22
- --container-6xl: 72rem;
23
22
  --font-weight-normal: 400;
24
23
  --tracking-wide: 0.025em;
25
24
  --radius-xs: 4px;
@@ -162,6 +161,8 @@
162
161
  --container-dialog: 420px;
163
162
  --container-sidebar: 240px;
164
163
  --container-sidebar-rail: 72px;
164
+ --container-palette: 640px;
165
+ --container-dialog-md: 560px;
165
166
  --grid-template-columns-system: repeat(12, minmax(0, 1fr));
166
167
  }
167
168
  }
@@ -818,6 +819,9 @@
818
819
  .max-h-64 {
819
820
  max-height: calc(var(--spacing) * 64);
820
821
  }
822
+ .max-h-full {
823
+ max-height: 100%;
824
+ }
821
825
  .min-h-0 {
822
826
  min-height: 0;
823
827
  }
@@ -926,17 +930,14 @@
926
930
  .max-w-5xl {
927
931
  max-width: var(--container-5xl);
928
932
  }
929
- .max-w-6xl {
930
- max-width: var(--container-6xl);
931
- }
932
933
  .max-w-16 {
933
934
  max-width: calc(var(--spacing) * 16);
934
935
  }
935
936
  .max-w-dialog {
936
937
  max-width: var(--container-dialog);
937
938
  }
938
- .max-w-drawer {
939
- max-width: var(--container-drawer);
939
+ .max-w-dialog-md {
940
+ max-width: var(--container-dialog-md);
940
941
  }
941
942
  .max-w-full {
942
943
  max-width: 100%;
@@ -944,6 +945,9 @@
944
945
  .max-w-md {
945
946
  max-width: var(--spacing-md);
946
947
  }
948
+ .max-w-palette {
949
+ max-width: var(--container-palette);
950
+ }
947
951
  .max-w-prose {
948
952
  max-width: 65ch;
949
953
  }
@@ -1611,6 +1615,12 @@
1611
1615
  .bg-semantic-error-soft {
1612
1616
  background-color: var(--color-semantic-error-soft);
1613
1617
  }
1618
+ .bg-semantic-error\/60 {
1619
+ background-color: color-mix(in srgb, #EA2261 60%, transparent);
1620
+ @supports (color: color-mix(in lab, red, red)) {
1621
+ background-color: color-mix(in oklab, var(--color-semantic-error) 60%, transparent);
1622
+ }
1623
+ }
1614
1624
  .bg-semantic-info-soft {
1615
1625
  background-color: var(--color-semantic-info-soft);
1616
1626
  }
@@ -1842,9 +1852,6 @@
1842
1852
  .pr-md {
1843
1853
  padding-right: var(--spacing-md);
1844
1854
  }
1845
- .pr-sm {
1846
- padding-right: var(--spacing-sm);
1847
- }
1848
1855
  .pr-xl {
1849
1856
  padding-right: var(--spacing-xl);
1850
1857
  }
@@ -2669,6 +2676,16 @@
2669
2676
  }
2670
2677
  }
2671
2678
  }
2679
+ .hover\:bg-semantic-error\/60 {
2680
+ &:hover {
2681
+ @media (hover: hover) {
2682
+ background-color: color-mix(in srgb, #EA2261 60%, transparent);
2683
+ @supports (color: color-mix(in lab, red, red)) {
2684
+ background-color: color-mix(in oklab, var(--color-semantic-error) 60%, transparent);
2685
+ }
2686
+ }
2687
+ }
2688
+ }
2672
2689
  .hover\:bg-surface-soft {
2673
2690
  &:hover {
2674
2691
  @media (hover: hover) {
@@ -2739,6 +2756,13 @@
2739
2756
  }
2740
2757
  }
2741
2758
  }
2759
+ .hover\:text-semantic-error {
2760
+ &:hover {
2761
+ @media (hover: hover) {
2762
+ color: var(--color-semantic-error);
2763
+ }
2764
+ }
2765
+ }
2742
2766
  .hover\:underline {
2743
2767
  &:hover {
2744
2768
  @media (hover: hover) {
@@ -2793,6 +2817,11 @@
2793
2817
  color: var(--color-primary);
2794
2818
  }
2795
2819
  }
2820
+ .focus-visible\:text-semantic-error {
2821
+ &:focus-visible {
2822
+ color: var(--color-semantic-error);
2823
+ }
2824
+ }
2796
2825
  .focus-visible\:ring-0 {
2797
2826
  &:focus-visible {
2798
2827
  --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
@@ -2919,6 +2948,11 @@
2919
2948
  border-color: var(--color-primary-active);
2920
2949
  }
2921
2950
  }
2951
+ .active\:border-semantic-error {
2952
+ &:active {
2953
+ border-color: var(--color-semantic-error);
2954
+ }
2955
+ }
2922
2956
  .active\:border-transparent {
2923
2957
  &:active {
2924
2958
  border-color: transparent;
@@ -2950,6 +2984,11 @@
2950
2984
  }
2951
2985
  }
2952
2986
  }
2987
+ .active\:bg-semantic-error {
2988
+ &:active {
2989
+ background-color: var(--color-semantic-error);
2990
+ }
2991
+ }
2953
2992
  .active\:bg-surface-soft {
2954
2993
  &:active {
2955
2994
  background-color: var(--color-surface-soft);
@@ -3045,6 +3084,14 @@
3045
3084
  }
3046
3085
  }
3047
3086
  }
3087
+ .disabled\:bg-semantic-error\/60 {
3088
+ &:disabled {
3089
+ background-color: color-mix(in srgb, #EA2261 60%, transparent);
3090
+ @supports (color: color-mix(in lab, red, red)) {
3091
+ background-color: color-mix(in oklab, var(--color-semantic-error) 60%, transparent);
3092
+ }
3093
+ }
3094
+ }
3048
3095
  .disabled\:bg-surface-soft {
3049
3096
  &:disabled {
3050
3097
  background-color: var(--color-surface-soft);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@designa8/vibedesign-stripe-deepseek-2-176b",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Complete design system \"My Project stripe-deepseek\" generated by Atoms Design.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -3,6 +3,8 @@ import * as React from "react";
3
3
  type ButtonVariant =
4
4
  | "primary"
5
5
  | "primary-soft"
6
+ | "danger"
7
+ | "danger-soft"
6
8
  | "secondary"
7
9
  | "outline"
8
10
  | "outline-soft"
@@ -88,6 +90,21 @@ const variantStyles: Record<ButtonVariant, string> = {
88
90
  "focus-visible:bg-canvas focus-visible:text-primary focus-visible:border-primary focus-visible:ring-focus-blue/40",
89
91
  "disabled:bg-primary-disabled disabled:text-muted disabled:border-transparent",
90
92
  ),
93
+ /**
94
+ * The destructive twin of `primary`: the same filled geometry on the error
95
+ * hue, for the action that removes money, deletes a record, or ends access.
96
+ * Hover inverts to the error outline exactly like the brand fill, so the
97
+ * paired footer keeps one press grammar whichever tone the commit wears.
98
+ */
99
+ danger: cn(
100
+ focusRing,
101
+ "justify-center rounded-xl active:scale-[0.98]",
102
+ "border-2 bg-semantic-error text-on-primary border-transparent",
103
+ "hover:bg-canvas hover:text-semantic-error hover:border-semantic-error",
104
+ "active:bg-semantic-error active:text-on-primary active:border-semantic-error",
105
+ "focus-visible:bg-canvas focus-visible:text-semantic-error focus-visible:border-semantic-error focus-visible:ring-focus-blue/40",
106
+ "disabled:bg-primary-disabled disabled:text-muted disabled:border-transparent",
107
+ ),
91
108
  /**
92
109
  * The same filled pill at reduced strength: the action is committed and the
93
110
  * request is in flight, so the control keeps its size, its label, and the
@@ -102,6 +119,19 @@ const variantStyles: Record<ButtonVariant, string> = {
102
119
  "focus-visible:ring-focus-blue/40",
103
120
  "disabled:pointer-events-none disabled:border-transparent disabled:bg-primary/60 disabled:text-on-primary",
104
121
  ),
122
+ /**
123
+ * The dimmed destructive twin, used while a destructive request is in
124
+ * flight: it holds the pill's size and label, keeps the error hue, and pins
125
+ * the fill so a working control can never be hovered brighter.
126
+ */
127
+ "danger-soft": cn(
128
+ focusRing,
129
+ "justify-center rounded-xl active:scale-[0.98]",
130
+ "border-transparent bg-semantic-error/60 text-on-primary",
131
+ "hover:bg-semantic-error/60 hover:text-on-primary hover:border-transparent",
132
+ "focus-visible:ring-focus-blue/40",
133
+ "disabled:pointer-events-none disabled:border-transparent disabled:bg-semantic-error/60 disabled:text-on-primary",
134
+ ),
105
135
  // Persistent outline treatment.
106
136
  secondary: cn(
107
137
  focusRing,
@@ -1,77 +1,228 @@
1
1
  import * as React from "react";
2
2
  import { DataTableDesktop } from "../DataTableDesktop";
3
- import type { PaymentRow } from "../DataTableDesktop";
3
+ import type {
4
+ DataTableBaseRow,
5
+ DataTableColumn,
6
+ DataTableDesktopProps,
7
+ DataTableFilter,
8
+ DataTableRange,
9
+ } from "../DataTableDesktop";
4
10
  import { DataTableMobile } from "../DataTableMobile";
5
- import type { MobilePaymentRow } from "../DataTableMobile";
11
+ import type {
12
+ DataTableMobileRowSpec,
13
+ DataTableMobileProps,
14
+ } from "../DataTableMobile";
6
15
 
7
16
  const cn = (...values: Array<string | false | null | undefined>) =>
8
17
  values.filter(Boolean).join(" ");
9
18
 
10
- export interface DataTableProps
19
+ /**
20
+ * The generic table contract. `columns` drives the wide layout and `mobileRow`
21
+ * drives the stacked one; everything else is shared, so both halves always show
22
+ * the same filtered, searched, sorted, selected and paginated slice.
23
+ */
24
+ export interface DataTableProps<T extends DataTableBaseRow = DataTableBaseRow>
11
25
  extends Omit<React.ComponentPropsWithoutRef<"div">, "onChange" | "title"> {
12
- /**
13
- * Ledger lines for the wide layout. The desktop ledger needs the fee and net
14
- * split, so it takes the richer row shape.
15
- */
16
- desktopRows?: PaymentRow[];
17
- /**
18
- * Ledger lines for the narrow layout. The stacked row shows the payment and
19
- * its amount only, so it takes its own lighter row shape.
20
- */
21
- mobileRows?: MobilePaymentRow[];
22
- /** Total payments in the ledger, used by the desktop range caption and pager. */
23
- totalCount?: number;
26
+ /** Column definitions for the wide layout. */
27
+ columns?: Array<DataTableColumn<T>>;
28
+ /** Rows to render, in both layouts. */
29
+ rows?: T[];
30
+ /** Stable row identity, defaults to `row.id`. */
31
+ getRowId?: (row: T) => string;
32
+ /** How one row collapses into the stacked mobile line. */
33
+ mobileRow?: DataTableMobileRowSpec<T>;
34
+ /** Filter chips shown above the table. */
35
+ filters?: DataTableFilter[];
36
+ filter?: string;
37
+ defaultFilter?: string;
38
+ onFilterChange?: (value: string) => void;
39
+ filterBy?: (row: T, value: string) => boolean;
40
+ searchPlaceholder?: string;
41
+ query?: string;
42
+ onQueryChange?: (value: string) => void;
43
+ searchBy?: (row: T) => string;
44
+ /** Date-range presets. The trigger is hidden when omitted. */
45
+ ranges?: DataTableRange[];
46
+ range?: string;
47
+ onRangeChange?: (value: string) => void;
48
+ /** Replaces the export / contact-sales pair. */
49
+ toolbar?: React.ReactNode;
50
+ onRowClick?: (row: T) => void;
51
+ selectable?: boolean;
52
+ selectedIds?: string[];
53
+ onSelectionChange?: (ids: string[]) => void;
54
+ bulkActions?: (ids: string[]) => React.ReactNode;
24
55
  /** Rows per page in the wide layout. */
25
56
  pageSize?: number;
26
57
  /** Rows per page in the narrow layout. */
27
58
  mobilePageSize?: number;
28
- /** Placeholder copy inside the narrow layout's search pill. */
29
- searchPlaceholder?: string;
59
+ totalCount?: number;
60
+ itemLabel?: string;
61
+ emptyTitle?: React.ReactNode;
62
+ emptyDescription?: React.ReactNode;
63
+ emptyAction?: React.ReactNode;
64
+ dense?: boolean;
65
+ title?: React.ReactNode;
66
+ description?: React.ReactNode;
67
+
68
+ /** @deprecated legacy alias for `rows` on the wide layout. */
69
+ desktopRows?: DataTableDesktopProps["rows"];
70
+ /** @deprecated legacy alias for `rows` on the narrow layout. */
71
+ mobileRows?: DataTableMobileProps["rows"];
30
72
  }
31
73
 
32
74
  /**
33
- * The payments ledger, responsive by breakpoint rather than by JavaScript.
34
- *
35
- * It is a thin composition wrapper: both the desktop and the mobile ledger stay
36
- * mounted in the tree, and only their visibility flips at this system's `md`
37
- * breakpoint (768px) — `hidden md:block` around the desktop layout, `md:hidden`
38
- * around the mobile one. No viewport measurement, no hydration mismatch, and no
39
- * layout reimplementation: each half keeps its own toolbar, rows, and pager.
75
+ * One responsive table: both halves stay mounted and only their visibility
76
+ * flips at this system's `md` breakpoint (768px) — `hidden md:block` around the
77
+ * wide layout, `md:hidden` around the stacked one. No viewport measurement and
78
+ * no hydration mismatch.
40
79
  *
41
- * Because both halves are always mounted, their local state (search text,
42
- * filters, page) survives a window resize in either direction.
80
+ * The wrapper owns the shared state — filter, query, range, selection and page
81
+ * — so resizing never loses what the reader was looking at, and a hidden half
82
+ * never paginates or filters differently from the visible one.
43
83
  */
44
- export const DataTable = React.forwardRef<HTMLDivElement, DataTableProps>(
45
- (
46
- {
47
- desktopRows,
48
- mobileRows,
49
- totalCount,
50
- pageSize,
51
- mobilePageSize,
52
- searchPlaceholder,
53
- className,
54
- ...rest
55
- },
56
- ref,
57
- ) => (
84
+ function DataTableInner<T extends DataTableBaseRow>(
85
+ props: DataTableProps<T>,
86
+ ref: React.Ref<HTMLDivElement>,
87
+ ) {
88
+ const {
89
+ columns,
90
+ rows,
91
+ getRowId,
92
+ mobileRow,
93
+ filters,
94
+ filter,
95
+ defaultFilter,
96
+ onFilterChange,
97
+ filterBy,
98
+ searchPlaceholder,
99
+ query,
100
+ onQueryChange,
101
+ searchBy,
102
+ ranges,
103
+ range,
104
+ onRangeChange,
105
+ toolbar,
106
+ onRowClick,
107
+ selectable,
108
+ selectedIds,
109
+ onSelectionChange,
110
+ bulkActions,
111
+ pageSize,
112
+ mobilePageSize,
113
+ totalCount,
114
+ itemLabel,
115
+ emptyTitle,
116
+ emptyDescription,
117
+ emptyAction,
118
+ dense,
119
+ title,
120
+ description,
121
+ desktopRows,
122
+ mobileRows,
123
+ className,
124
+ ...rest
125
+ } = props;
126
+
127
+ const legacyRows = rows === undefined && desktopRows !== undefined;
128
+
129
+ const [innerQuery, setInnerQuery] = React.useState("");
130
+ const activeQuery = query ?? innerQuery;
131
+
132
+ const [innerFilter, setInnerFilter] = React.useState(
133
+ defaultFilter ?? filters?.[0]?.value ?? "all",
134
+ );
135
+ const activeFilter = filter ?? innerFilter;
136
+
137
+ const [innerRange, setInnerRange] = React.useState(ranges?.[0]?.value ?? "");
138
+ const activeRangeValue = range ?? innerRange;
139
+
140
+ const [innerSelected, setInnerSelected] = React.useState<string[]>([]);
141
+ const activeSelected = selectedIds ?? innerSelected;
142
+
143
+ const handleQuery = (next: string) => {
144
+ if (query === undefined) setInnerQuery(next);
145
+ onQueryChange?.(next);
146
+ };
147
+
148
+ const handleFilter = (next: string) => {
149
+ if (filter === undefined) setInnerFilter(next);
150
+ onFilterChange?.(next);
151
+ };
152
+
153
+ const handleRange = (next: string) => {
154
+ if (range === undefined) setInnerRange(next);
155
+ onRangeChange?.(next);
156
+ };
157
+
158
+ const handleSelection = (next: string[]) => {
159
+ if (selectedIds === undefined) setInnerSelected(next);
160
+ onSelectionChange?.(next);
161
+ };
162
+
163
+ const shared = {
164
+ getRowId,
165
+ filters,
166
+ filter: activeFilter,
167
+ onFilterChange: handleFilter,
168
+ filterBy,
169
+ searchPlaceholder,
170
+ query: activeQuery,
171
+ onQueryChange: handleQuery,
172
+ searchBy,
173
+ ranges,
174
+ range: activeRangeValue,
175
+ onRangeChange: handleRange,
176
+ toolbar,
177
+ onRowClick,
178
+ selectable,
179
+ selectedIds: activeSelected,
180
+ onSelectionChange: handleSelection,
181
+ bulkActions,
182
+ totalCount,
183
+ itemLabel,
184
+ emptyTitle,
185
+ emptyDescription,
186
+ emptyAction,
187
+ dense,
188
+ title,
189
+ description,
190
+ };
191
+
192
+ const desktopRowData = legacyRows
193
+ ? desktopRows
194
+ : (rows ?? (desktopRows as T[] | undefined));
195
+
196
+ const mobileRowData = rows ?? (mobileRows as T[] | undefined);
197
+
198
+ return (
58
199
  <div ref={ref} className={cn("w-full", className)} {...rest}>
59
200
  <div className="hidden w-full md:block">
60
- <DataTableDesktop
61
- rows={desktopRows}
62
- totalCount={totalCount}
201
+ <DataTableDesktop<T>
202
+ {...shared}
203
+ columns={columns}
204
+ rows={desktopRowData as T[]}
63
205
  pageSize={pageSize}
64
206
  />
65
207
  </div>
66
208
  <div className="w-full md:hidden">
67
- <DataTableMobile
68
- rows={mobileRows}
209
+ <DataTableMobile<T>
210
+ {...shared}
211
+ mobileRow={mobileRow}
212
+ rows={mobileRowData as T[]}
69
213
  pageSize={mobilePageSize}
70
- searchPlaceholder={searchPlaceholder}
71
214
  />
72
215
  </div>
73
216
  </div>
74
- ),
75
- );
217
+ );
218
+ }
219
+
220
+ type DataTableComponent = <T extends DataTableBaseRow = DataTableBaseRow>(
221
+ props: DataTableProps<T> & React.RefAttributes<HTMLDivElement>,
222
+ ) => React.ReactElement | null;
223
+
224
+ export const DataTable = React.forwardRef(
225
+ DataTableInner,
226
+ ) as unknown as DataTableComponent;
76
227
 
77
- DataTable.displayName = "DataTable";
228
+ (DataTable as { displayName?: string }).displayName = "DataTable";
@@ -1,2 +1,14 @@
1
1
  export { DataTable } from "./DataTable";
2
2
  export type { DataTableProps } from "./DataTable";
3
+ export type {
4
+ DataTableAlign,
5
+ DataTableBaseRow,
6
+ DataTableColumn,
7
+ DataTableFilter,
8
+ DataTableRange,
9
+ } from "../DataTableDesktop";
10
+ export type {
11
+ DataTableMobileFilter,
12
+ DataTableMobileRange,
13
+ DataTableMobileRowSpec,
14
+ } from "../DataTableMobile";