@lindaui/blocks 0.0.3 → 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/dist/document-panel.d.ts +7 -1
- package/dist/document-panel.d.ts.map +1 -1
- package/dist/document-panel.js +26 -8
- package/dist/field-array-form.d.ts.map +1 -1
- package/dist/field-array-form.js +22 -16
- package/dist/list-pane.d.ts.map +1 -1
- package/dist/list-pane.js +7 -17
- package/dist/recording-overlay.d.ts +9 -1
- package/dist/recording-overlay.d.ts.map +1 -1
- package/dist/recording-overlay.js +28 -10
- package/dist/split-workspace.d.ts +8 -1
- package/dist/split-workspace.d.ts.map +1 -1
- package/dist/split-workspace.js +12 -4
- package/dist/table-pane.d.ts +44 -0
- package/dist/table-pane.d.ts.map +1 -0
- package/dist/table-pane.js +137 -0
- package/dist/workspace-back-button.d.ts +15 -0
- package/dist/workspace-back-button.d.ts.map +1 -0
- package/dist/workspace-back-button.js +19 -0
- package/llms.txt +29 -3
- package/package.json +11 -3
package/dist/document-panel.d.ts
CHANGED
|
@@ -3,6 +3,12 @@ export interface DocumentPanelProps {
|
|
|
3
3
|
title: string;
|
|
4
4
|
subtitle?: ReactNode;
|
|
5
5
|
meta?: ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* `block` (default) stacks subtitle and meta on their own lines. `inline`
|
|
8
|
+
* flows them on one wrapping row (subtitle · meta) so a date sits next to the
|
|
9
|
+
* subtitle instead of forcing a new line.
|
|
10
|
+
*/
|
|
11
|
+
metaPlacement?: "block" | "inline";
|
|
6
12
|
statusBadge?: ReactNode;
|
|
7
13
|
state: "empty" | "loading" | "ready";
|
|
8
14
|
emptyContent?: ReactNode;
|
|
@@ -11,5 +17,5 @@ export interface DocumentPanelProps {
|
|
|
11
17
|
children?: ReactNode;
|
|
12
18
|
footer?: ReactNode;
|
|
13
19
|
}
|
|
14
|
-
export declare function DocumentPanel({ title, subtitle, meta, statusBadge, state, emptyContent, loadingLabel, notices, children, footer, }: DocumentPanelProps): import("react").JSX.Element;
|
|
20
|
+
export declare function DocumentPanel({ title, subtitle, meta, metaPlacement, statusBadge, state, emptyContent, loadingLabel, notices, children, footer, }: DocumentPanelProps): import("react").JSX.Element;
|
|
15
21
|
//# sourceMappingURL=document-panel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-panel.d.ts","sourceRoot":"","sources":["../src/document-panel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACrC,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,WAAW,EACX,KAAK,EACL,YAAY,EACZ,YAA0B,EAC1B,OAAO,EACP,QAAQ,EACR,MAAM,GACP,EAAE,kBAAkB,+
|
|
1
|
+
{"version":3,"file":"document-panel.d.ts","sourceRoot":"","sources":["../src/document-panel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACnC,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACrC,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,aAAuB,EACvB,WAAW,EACX,KAAK,EACL,YAAY,EACZ,YAA0B,EAC1B,OAAO,EACP,QAAQ,EACR,MAAM,GACP,EAAE,kBAAkB,+BAuEpB"}
|
package/dist/document-panel.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import { Divider } from '@lindaui/ui/divider';
|
|
3
3
|
import { Skeleton } from '@lindaui/ui/skeleton';
|
|
4
4
|
|
|
5
|
-
function DocumentPanel({ title, subtitle, meta, statusBadge, state, emptyContent, loadingLabel = "Cargando…", notices, children, footer }) {
|
|
5
|
+
function DocumentPanel({ title, subtitle, meta, metaPlacement = "block", statusBadge, state, emptyContent, loadingLabel = "Cargando…", notices, children, footer }) {
|
|
6
6
|
return /*#__PURE__*/ jsxs("div", {
|
|
7
7
|
className: "flex flex-col h-full",
|
|
8
8
|
children: [
|
|
@@ -16,13 +16,31 @@ function DocumentPanel({ title, subtitle, meta, statusBadge, state, emptyContent
|
|
|
16
16
|
className: "truncate text-lg font-bold leading-tight tracking-tight sm:text-xl",
|
|
17
17
|
children: title
|
|
18
18
|
}),
|
|
19
|
-
subtitle && /*#__PURE__*/
|
|
20
|
-
className: "mt-0.5 text-sm text-muted-foreground",
|
|
21
|
-
children:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
metaPlacement === "inline" ? (subtitle || meta) && /*#__PURE__*/ jsxs("div", {
|
|
20
|
+
className: "mt-0.5 flex flex-wrap items-center gap-x-2 text-sm text-muted-foreground",
|
|
21
|
+
children: [
|
|
22
|
+
subtitle && /*#__PURE__*/ jsx("span", {
|
|
23
|
+
children: subtitle
|
|
24
|
+
}),
|
|
25
|
+
meta && /*#__PURE__*/ jsxs("span", {
|
|
26
|
+
className: "text-xs tabular-nums",
|
|
27
|
+
children: [
|
|
28
|
+
subtitle ? "· " : "",
|
|
29
|
+
meta
|
|
30
|
+
]
|
|
31
|
+
})
|
|
32
|
+
]
|
|
33
|
+
}) : /*#__PURE__*/ jsxs(Fragment, {
|
|
34
|
+
children: [
|
|
35
|
+
subtitle && /*#__PURE__*/ jsx("p", {
|
|
36
|
+
className: "mt-0.5 text-sm text-muted-foreground",
|
|
37
|
+
children: subtitle
|
|
38
|
+
}),
|
|
39
|
+
meta && /*#__PURE__*/ jsx("p", {
|
|
40
|
+
className: "mt-0.5 text-xs text-muted-foreground tabular-nums",
|
|
41
|
+
children: meta
|
|
42
|
+
})
|
|
43
|
+
]
|
|
26
44
|
})
|
|
27
45
|
]
|
|
28
46
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-array-form.d.ts","sourceRoot":"","sources":["../src/field-array-form.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC/C;AAED,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,OAAO,EACP,aAA2B,EAC3B,SAAoB,EACpB,eAAe,EACf,YAAyB,EACzB,QAA4B,EAC5B,WAAgC,EAChC,cAAwB,EACxB,gBAA0B,EAC1B,SAAS,EACT,WAAuB,EACvB,OAAe,EACf,aAAa,GACd,EAAE,mBAAmB,+
|
|
1
|
+
{"version":3,"file":"field-array-form.d.ts","sourceRoot":"","sources":["../src/field-array-form.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC/C;AAED,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,OAAO,EACP,aAA2B,EAC3B,SAAoB,EACpB,eAAe,EACf,YAAyB,EACzB,QAA4B,EAC5B,WAAgC,EAChC,cAAwB,EACxB,gBAA0B,EAC1B,SAAS,EACT,WAAuB,EACvB,OAAe,EACf,aAAa,GACd,EAAE,mBAAmB,+BAuHrB"}
|
package/dist/field-array-form.js
CHANGED
|
@@ -70,27 +70,33 @@ function FieldArrayForm({ onSubmit, options, categoryLabel = "Categoría", nameL
|
|
|
70
70
|
/*#__PURE__*/ jsx(Controller, {
|
|
71
71
|
control: control,
|
|
72
72
|
name: `entries.${index}.key`,
|
|
73
|
-
render: ({ field: f })=>/*#__PURE__*/ jsx(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
render: ({ field: f })=>/*#__PURE__*/ jsx("div", {
|
|
74
|
+
className: "min-w-0 w-full",
|
|
75
|
+
children: /*#__PURE__*/ jsx(Input, {
|
|
76
|
+
placeholder: keyPlaceholder,
|
|
77
|
+
"aria-label": `${keyPlaceholder} ${index + 1}`,
|
|
78
|
+
value: f.value,
|
|
79
|
+
onChange: f.onChange,
|
|
80
|
+
onBlur: f.onBlur,
|
|
81
|
+
name: f.name,
|
|
82
|
+
fullWidth: true
|
|
83
|
+
})
|
|
81
84
|
})
|
|
82
85
|
}),
|
|
83
86
|
/*#__PURE__*/ jsx(Controller, {
|
|
84
87
|
control: control,
|
|
85
88
|
name: `entries.${index}.value`,
|
|
86
|
-
render: ({ field: f })=>/*#__PURE__*/ jsx(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
render: ({ field: f })=>/*#__PURE__*/ jsx("div", {
|
|
90
|
+
className: "min-w-0 w-full",
|
|
91
|
+
children: /*#__PURE__*/ jsx(Input, {
|
|
92
|
+
placeholder: valuePlaceholder,
|
|
93
|
+
"aria-label": `${valuePlaceholder} ${index + 1}`,
|
|
94
|
+
value: f.value,
|
|
95
|
+
onChange: f.onChange,
|
|
96
|
+
onBlur: f.onBlur,
|
|
97
|
+
name: f.name,
|
|
98
|
+
fullWidth: true
|
|
99
|
+
})
|
|
94
100
|
})
|
|
95
101
|
}),
|
|
96
102
|
/*#__PURE__*/ jsx(Button, {
|
package/dist/list-pane.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-pane.d.ts","sourceRoot":"","sources":["../src/list-pane.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAM9C,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,YAAY,EACZ,cAAc,EACd,WAAgB,EAChB,cAAc,EACd,iBAA4B,EAC5B,WAAsB,EACtB,OAAe,EACf,KAAY,EACZ,OAAO,EACP,UAA8C,EAC9C,UAAyB,EACzB,OAAO,EACP,UAA6B,EAC7B,gBAAgB,EAChB,SAAS,EACT,QAAQ,GACT,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"list-pane.d.ts","sourceRoot":"","sources":["../src/list-pane.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAM9C,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,YAAY,EACZ,cAAc,EACd,WAAgB,EAChB,cAAc,EACd,iBAA4B,EAC5B,WAAsB,EACtB,OAAe,EACf,KAAY,EACZ,OAAO,EACP,UAA8C,EAC9C,UAAyB,EACzB,OAAO,EACP,UAA6B,EAC7B,gBAAgB,EAChB,SAAS,EACT,QAAQ,GACT,EAAE,aAAa,qBA2Ff"}
|
package/dist/list-pane.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { AlertCircle, RotateCcw, FileText } from 'lucide-react';
|
|
5
5
|
import { Button } from '@lindaui/ui/button';
|
|
6
|
-
import {
|
|
6
|
+
import { SearchField } from '@lindaui/ui/search-field';
|
|
7
7
|
import { Skeleton } from '@lindaui/ui/skeleton';
|
|
8
8
|
|
|
9
9
|
function ListPane({ filters, activeFilter, onFilterChange, searchValue = "", onSearchChange, searchPlaceholder = "Buscar", searchLabel = "Buscar", loading = false, error = null, onRetry, errorTitle = "No se pudieron cargar los datos", retryLabel = "Reintentar", isEmpty, emptyTitle = "Sin resultados", emptyDescription, emptyIcon, children }) {
|
|
@@ -30,21 +30,11 @@ function ListPane({ filters, activeFilter, onFilterChange, searchValue = "", onS
|
|
|
30
30
|
]
|
|
31
31
|
}, f.key))
|
|
32
32
|
}),
|
|
33
|
-
/*#__PURE__*/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}),
|
|
39
|
-
/*#__PURE__*/ jsx(Input, {
|
|
40
|
-
type: "search",
|
|
41
|
-
value: searchValue,
|
|
42
|
-
onChange: onSearchChange ?? (()=>{}),
|
|
43
|
-
placeholder: searchPlaceholder,
|
|
44
|
-
"aria-label": searchLabel,
|
|
45
|
-
className: "h-9 pl-8"
|
|
46
|
-
})
|
|
47
|
-
]
|
|
33
|
+
/*#__PURE__*/ jsx(SearchField, {
|
|
34
|
+
value: searchValue,
|
|
35
|
+
onChange: onSearchChange ?? (()=>{}),
|
|
36
|
+
placeholder: searchPlaceholder,
|
|
37
|
+
"aria-label": searchLabel
|
|
48
38
|
})
|
|
49
39
|
]
|
|
50
40
|
}),
|
|
@@ -8,6 +8,14 @@ export interface RecordingOverlayProps {
|
|
|
8
8
|
stopLabel?: string;
|
|
9
9
|
errorTitle?: string;
|
|
10
10
|
backLabel?: string;
|
|
11
|
+
/**
|
|
12
|
+
* `overlay` (default) covers its container on a fixed dark surface (`viewer-*`
|
|
13
|
+
* tokens) — for use over media. `inline` drops the absolute positioning and the
|
|
14
|
+
* forced dark background, filling its container and inheriting the panel's
|
|
15
|
+
* surface; its text is token-driven so it stays legible on a light or dark
|
|
16
|
+
* panel. Content is otherwise identical.
|
|
17
|
+
*/
|
|
18
|
+
variant?: "overlay" | "inline";
|
|
11
19
|
}
|
|
12
|
-
export declare function RecordingOverlay({ label, description, elapsed, error, onStop, onCancel, stopLabel, errorTitle, backLabel, }: RecordingOverlayProps): import("react").JSX.Element;
|
|
20
|
+
export declare function RecordingOverlay({ label, description, elapsed, error, onStop, onCancel, stopLabel, errorTitle, backLabel, variant, }: RecordingOverlayProps): import("react").JSX.Element;
|
|
13
21
|
//# sourceMappingURL=recording-overlay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recording-overlay.d.ts","sourceRoot":"","sources":["../src/recording-overlay.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"recording-overlay.d.ts","sourceRoot":"","sources":["../src/recording-overlay.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAChC;AAsDD,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,WAAW,EACX,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAqB,EACrB,UAA8C,EAC9C,SAAoB,EACpB,OAAmB,GACpB,EAAE,qBAAqB,+BAuEvB"}
|
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { AlertCircle, Mic } from 'lucide-react';
|
|
4
4
|
|
|
5
|
+
/** Per-variant surface/text tokens so both read on their respective background. */ function variantTokens(variant) {
|
|
6
|
+
if (variant === "inline") {
|
|
7
|
+
return {
|
|
8
|
+
root: "ti-fade flex h-full flex-col items-center justify-center gap-5 p-6 sm:gap-7",
|
|
9
|
+
text: "text-foreground",
|
|
10
|
+
muted: "text-muted-foreground",
|
|
11
|
+
// solid action button on an adaptive panel
|
|
12
|
+
solid: "bg-foreground text-background"
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
root: "ti-fade absolute inset-0 z-[60] flex flex-col items-center justify-center gap-5 bg-viewer-bg p-8 text-viewer-foreground sm:gap-7",
|
|
17
|
+
text: "text-viewer-foreground",
|
|
18
|
+
muted: "text-viewer-foreground/70",
|
|
19
|
+
solid: "bg-white text-[oklch(0.16_0.02_240)]"
|
|
20
|
+
};
|
|
21
|
+
}
|
|
5
22
|
function fmtTime(sec) {
|
|
6
23
|
const m = Math.floor(sec / 60);
|
|
7
24
|
const s = sec % 60;
|
|
@@ -30,10 +47,11 @@ function Waveform() {
|
|
|
30
47
|
})
|
|
31
48
|
});
|
|
32
49
|
}
|
|
33
|
-
function RecordingOverlay({ label, description, elapsed, error, onStop, onCancel, stopLabel = "Detener", errorTitle = "No se pudo acceder al micrófono", backLabel = "Volver" }) {
|
|
50
|
+
function RecordingOverlay({ label, description, elapsed, error, onStop, onCancel, stopLabel = "Detener", errorTitle = "No se pudo acceder al micrófono", backLabel = "Volver", variant = "overlay" }) {
|
|
51
|
+
const t = variantTokens(variant);
|
|
34
52
|
if (error) {
|
|
35
53
|
return /*#__PURE__*/ jsxs("div", {
|
|
36
|
-
className:
|
|
54
|
+
className: `${t.root} text-center`,
|
|
37
55
|
children: [
|
|
38
56
|
/*#__PURE__*/ jsx("div", {
|
|
39
57
|
className: "grid h-16 w-16 place-items-center rounded-full bg-destructive/15 text-destructive",
|
|
@@ -45,11 +63,11 @@ function RecordingOverlay({ label, description, elapsed, error, onStop, onCancel
|
|
|
45
63
|
className: "max-w-[280px]",
|
|
46
64
|
children: [
|
|
47
65
|
/*#__PURE__*/ jsx("p", {
|
|
48
|
-
className:
|
|
66
|
+
className: `text-base font-semibold ${t.text}`,
|
|
49
67
|
children: errorTitle
|
|
50
68
|
}),
|
|
51
69
|
/*#__PURE__*/ jsx("p", {
|
|
52
|
-
className:
|
|
70
|
+
className: `mt-2 text-sm ${t.muted}`,
|
|
53
71
|
children: error
|
|
54
72
|
})
|
|
55
73
|
]
|
|
@@ -57,14 +75,14 @@ function RecordingOverlay({ label, description, elapsed, error, onStop, onCancel
|
|
|
57
75
|
/*#__PURE__*/ jsx("button", {
|
|
58
76
|
type: "button",
|
|
59
77
|
onClick: onCancel,
|
|
60
|
-
className:
|
|
78
|
+
className: `h-12 rounded-2xl px-6 text-[15px] font-semibold ${t.solid}`,
|
|
61
79
|
children: backLabel
|
|
62
80
|
})
|
|
63
81
|
]
|
|
64
82
|
});
|
|
65
83
|
}
|
|
66
84
|
return /*#__PURE__*/ jsxs("div", {
|
|
67
|
-
className:
|
|
85
|
+
className: t.root,
|
|
68
86
|
children: [
|
|
69
87
|
/*#__PURE__*/ jsxs("div", {
|
|
70
88
|
className: "relative grid h-[132px] w-[132px] place-items-center sm:h-[168px] sm:w-[168px]",
|
|
@@ -96,26 +114,26 @@ function RecordingOverlay({ label, description, elapsed, error, onStop, onCancel
|
|
|
96
114
|
className: "ti-rec-blink h-2.5 w-2.5 rounded-full bg-destructive"
|
|
97
115
|
}),
|
|
98
116
|
/*#__PURE__*/ jsx("span", {
|
|
99
|
-
className: "text-sm font-semibold tracking-wide text-
|
|
117
|
+
className: "text-sm font-semibold tracking-wide text-destructive",
|
|
100
118
|
children: label
|
|
101
119
|
})
|
|
102
120
|
]
|
|
103
121
|
}),
|
|
104
122
|
/*#__PURE__*/ jsx("div", {
|
|
105
|
-
className:
|
|
123
|
+
className: `mt-2 font-mono text-4xl font-medium tabular-nums ${t.text} sm:text-[46px]`,
|
|
106
124
|
children: fmtTime(elapsed)
|
|
107
125
|
})
|
|
108
126
|
]
|
|
109
127
|
}),
|
|
110
128
|
/*#__PURE__*/ jsx(Waveform, {}),
|
|
111
129
|
description && /*#__PURE__*/ jsx("p", {
|
|
112
|
-
className:
|
|
130
|
+
className: `max-w-[270px] text-center text-sm leading-relaxed ${t.muted}`,
|
|
113
131
|
children: description
|
|
114
132
|
}),
|
|
115
133
|
/*#__PURE__*/ jsx("button", {
|
|
116
134
|
type: "button",
|
|
117
135
|
onClick: onStop,
|
|
118
|
-
className:
|
|
136
|
+
className: `mt-1.5 grid h-16 w-16 place-items-center rounded-full ${t.solid} shadow-[0_6px_20px_-4px_rgba(0,0,0,0.5)]`,
|
|
119
137
|
"aria-label": stopLabel,
|
|
120
138
|
children: /*#__PURE__*/ jsx("span", {
|
|
121
139
|
className: "h-6 w-6 rounded-md bg-destructive"
|
|
@@ -3,7 +3,14 @@ export interface SplitWorkspaceProps {
|
|
|
3
3
|
media: ReactNode;
|
|
4
4
|
panel: ReactNode;
|
|
5
5
|
overlay?: ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* Custom back control (escape hatch). Wins over `backHref`/`backLabel`.
|
|
8
|
+
* Prefer `backHref`/`backLabel` — the default renders a legible pill over
|
|
9
|
+
* any media without the consumer having to guarantee contrast.
|
|
10
|
+
*/
|
|
6
11
|
back?: ReactNode;
|
|
12
|
+
backHref?: string;
|
|
13
|
+
backLabel?: ReactNode;
|
|
7
14
|
}
|
|
8
|
-
export declare function SplitWorkspace({ media, panel, overlay, back, }: SplitWorkspaceProps): import("react").JSX.Element;
|
|
15
|
+
export declare function SplitWorkspace({ media, panel, overlay, back, backHref, backLabel, }: SplitWorkspaceProps): import("react").JSX.Element;
|
|
9
16
|
//# sourceMappingURL=split-workspace.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split-workspace.d.ts","sourceRoot":"","sources":["../src/split-workspace.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"split-workspace.d.ts","sourceRoot":"","sources":["../src/split-workspace.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,KAAK,EACL,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,SAAoB,GACrB,EAAE,mBAAmB,+BA8CrB"}
|
package/dist/split-workspace.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { useIsDesktop } from '@lindaui/ui/use-media-query';
|
|
4
|
+
import { WorkspaceBackButton } from './workspace-back-button.js';
|
|
4
5
|
|
|
5
|
-
function SplitWorkspace({ media, panel, overlay, back }) {
|
|
6
|
+
function SplitWorkspace({ media, panel, overlay, back, backHref, backLabel = "Volver" }) {
|
|
6
7
|
const isDesktop = useIsDesktop();
|
|
8
|
+
const backNode = back ?? (backHref != null ? /*#__PURE__*/ jsx(WorkspaceBackButton, {
|
|
9
|
+
href: backHref,
|
|
10
|
+
label: backLabel
|
|
11
|
+
}) : null);
|
|
7
12
|
return /*#__PURE__*/ jsxs("div", {
|
|
8
13
|
className: "relative flex-1 min-h-0 overflow-hidden",
|
|
9
14
|
children: [
|
|
@@ -35,9 +40,12 @@ function SplitWorkspace({ media, panel, overlay, back }) {
|
|
|
35
40
|
})
|
|
36
41
|
]
|
|
37
42
|
}),
|
|
38
|
-
|
|
39
|
-
className: "absolute
|
|
40
|
-
children:
|
|
43
|
+
backNode && /*#__PURE__*/ jsx("div", {
|
|
44
|
+
className: "pointer-events-none absolute inset-x-0 top-0 z-40 bg-linear-to-b from-black/25 to-transparent p-3 pt-[max(0.75rem,env(safe-area-inset-top))] pl-[max(0.875rem,env(safe-area-inset-left))]",
|
|
45
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
46
|
+
className: "pointer-events-auto inline-block",
|
|
47
|
+
children: backNode
|
|
48
|
+
})
|
|
41
49
|
}),
|
|
42
50
|
overlay && /*#__PURE__*/ jsx("div", {
|
|
43
51
|
className: "absolute inset-0 z-[60]",
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { type TableColumnDef } from "@lindaui/ui/table";
|
|
3
|
+
export interface TablePaneFilter {
|
|
4
|
+
key: string;
|
|
5
|
+
label: string;
|
|
6
|
+
count?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Tabular sibling of `list-pane`: the same controlled chrome (filter tabs +
|
|
10
|
+
* search + loading/error/empty states) wrapped around `@lindaui/ui/table`,
|
|
11
|
+
* plus a `toolbarExtra` slot and an optional footer. Zero data-fetching — the
|
|
12
|
+
* app passes already-filtered `rows` (each cell is a `ReactNode`, so domain
|
|
13
|
+
* chips/avatars live in the consumer) and owns all state.
|
|
14
|
+
*/
|
|
15
|
+
export interface TablePaneProps {
|
|
16
|
+
columns: TableColumnDef[];
|
|
17
|
+
rows: Record<string, ReactNode>[];
|
|
18
|
+
ariaLabel?: string;
|
|
19
|
+
filters?: TablePaneFilter[];
|
|
20
|
+
activeFilter?: string;
|
|
21
|
+
onFilterChange?: (key: string) => void;
|
|
22
|
+
searchValue?: string;
|
|
23
|
+
onSearchChange?: (value: string) => void;
|
|
24
|
+
searchPlaceholder?: string;
|
|
25
|
+
searchLabel?: string;
|
|
26
|
+
toolbarExtra?: ReactNode;
|
|
27
|
+
loading?: boolean;
|
|
28
|
+
error?: string | null;
|
|
29
|
+
onRetry?: () => void;
|
|
30
|
+
errorTitle?: string;
|
|
31
|
+
retryLabel?: string;
|
|
32
|
+
isEmpty?: boolean;
|
|
33
|
+
emptyTitle?: string;
|
|
34
|
+
emptyDescription?: ReactNode;
|
|
35
|
+
emptyIcon?: ReactNode;
|
|
36
|
+
footer?: ReactNode;
|
|
37
|
+
footerCount?: {
|
|
38
|
+
shown: number;
|
|
39
|
+
total: number;
|
|
40
|
+
label?: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export declare function TablePane({ columns, rows, ariaLabel, filters, activeFilter, onFilterChange, searchValue, onSearchChange, searchPlaceholder, searchLabel, toolbarExtra, loading, error, onRetry, errorTitle, retryLabel, isEmpty, emptyTitle, emptyDescription, emptyIcon, footer, footerCount, }: TablePaneProps): import("react").JSX.Element;
|
|
44
|
+
//# sourceMappingURL=table-pane.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-pane.d.ts","sourceRoot":"","sources":["../src/table-pane.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,OAAO,EAAS,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAE7B,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAGvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,YAAY,CAAC,EAAE,SAAS,CAAC;IAGzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC;IAGtB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChE;AAED,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,IAAI,EACJ,SAAmB,EACnB,OAAO,EACP,YAAY,EACZ,cAAc,EACd,WAAgB,EAChB,cAAc,EACd,iBAA4B,EAC5B,WAAsB,EACtB,YAAY,EACZ,OAAe,EACf,KAAY,EACZ,OAAO,EACP,UAAgC,EAChC,UAAyB,EACzB,OAAO,EACP,UAA6B,EAC7B,gBAAgB,EAChB,SAAS,EACT,MAAM,EACN,WAAW,GACZ,EAAE,cAAc,+BAiHhB"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { AlertCircle, RotateCcw, FileText } from 'lucide-react';
|
|
4
|
+
import { Button } from '@lindaui/ui/button';
|
|
5
|
+
import { SearchField } from '@lindaui/ui/search-field';
|
|
6
|
+
import { Skeleton } from '@lindaui/ui/skeleton';
|
|
7
|
+
import { Table } from '@lindaui/ui/table';
|
|
8
|
+
|
|
9
|
+
function TablePane({ columns, rows, ariaLabel = "Tabla", filters, activeFilter, onFilterChange, searchValue = "", onSearchChange, searchPlaceholder = "Buscar", searchLabel = "Buscar", toolbarExtra, loading = false, error = null, onRetry, errorTitle = "No se pudo cargar", retryLabel = "Reintentar", isEmpty, emptyTitle = "Sin resultados", emptyDescription, emptyIcon, footer, footerCount }) {
|
|
10
|
+
const showEmpty = !loading && !error && (isEmpty !== undefined ? isEmpty : rows.length === 0);
|
|
11
|
+
const showFooter = !loading && !error && (footer != null || footerCount != null);
|
|
12
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
13
|
+
className: "flex flex-col overflow-hidden rounded-xl border border-border bg-card",
|
|
14
|
+
children: [
|
|
15
|
+
filters && filters.length > 0 && /*#__PURE__*/ jsx("div", {
|
|
16
|
+
className: "flex flex-wrap gap-2 overflow-x-auto border-b border-border p-3",
|
|
17
|
+
children: filters.map((f)=>/*#__PURE__*/ jsxs(Button, {
|
|
18
|
+
variant: activeFilter === f.key ? "primary" : "ghost",
|
|
19
|
+
onPress: ()=>onFilterChange?.(f.key),
|
|
20
|
+
size: "sm",
|
|
21
|
+
children: [
|
|
22
|
+
f.label,
|
|
23
|
+
f.count != null && /*#__PURE__*/ jsx("span", {
|
|
24
|
+
"aria-hidden": true,
|
|
25
|
+
className: "ml-1.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-muted-foreground/15 px-1 text-[11px] font-semibold tabular-nums text-muted-foreground",
|
|
26
|
+
children: f.count
|
|
27
|
+
})
|
|
28
|
+
]
|
|
29
|
+
}, f.key))
|
|
30
|
+
}),
|
|
31
|
+
(onSearchChange || toolbarExtra) && /*#__PURE__*/ jsxs("div", {
|
|
32
|
+
className: "flex flex-wrap items-center gap-3 border-b border-border p-4",
|
|
33
|
+
children: [
|
|
34
|
+
onSearchChange && /*#__PURE__*/ jsx("div", {
|
|
35
|
+
className: "min-w-[240px] flex-1",
|
|
36
|
+
children: /*#__PURE__*/ jsx(SearchField, {
|
|
37
|
+
value: searchValue,
|
|
38
|
+
onChange: onSearchChange,
|
|
39
|
+
placeholder: searchPlaceholder,
|
|
40
|
+
"aria-label": searchLabel
|
|
41
|
+
})
|
|
42
|
+
}),
|
|
43
|
+
toolbarExtra
|
|
44
|
+
]
|
|
45
|
+
}),
|
|
46
|
+
/*#__PURE__*/ jsxs("div", {
|
|
47
|
+
className: "min-h-0 flex-1 overflow-x-auto",
|
|
48
|
+
children: [
|
|
49
|
+
loading && /*#__PURE__*/ jsx("div", {
|
|
50
|
+
role: "status",
|
|
51
|
+
"aria-label": "Cargando",
|
|
52
|
+
className: "space-y-2 p-3",
|
|
53
|
+
children: Array.from({
|
|
54
|
+
length: 6
|
|
55
|
+
}).map((_, i)=>/*#__PURE__*/ jsx(Skeleton, {
|
|
56
|
+
className: "h-12 w-full"
|
|
57
|
+
}, i))
|
|
58
|
+
}),
|
|
59
|
+
!loading && error && /*#__PURE__*/ jsxs("div", {
|
|
60
|
+
className: "m-3 rounded-xl border border-destructive/35 bg-destructive/5 p-6 text-center",
|
|
61
|
+
children: [
|
|
62
|
+
/*#__PURE__*/ jsx(AlertCircle, {
|
|
63
|
+
className: "mx-auto h-6 w-6 text-destructive"
|
|
64
|
+
}),
|
|
65
|
+
/*#__PURE__*/ jsx("p", {
|
|
66
|
+
className: "mt-2 text-sm font-semibold",
|
|
67
|
+
children: errorTitle
|
|
68
|
+
}),
|
|
69
|
+
/*#__PURE__*/ jsx("p", {
|
|
70
|
+
className: "mt-1 text-xs text-muted-foreground",
|
|
71
|
+
children: error
|
|
72
|
+
}),
|
|
73
|
+
onRetry && /*#__PURE__*/ jsxs(Button, {
|
|
74
|
+
variant: "secondary",
|
|
75
|
+
size: "sm",
|
|
76
|
+
onPress: onRetry,
|
|
77
|
+
className: "mt-3",
|
|
78
|
+
children: [
|
|
79
|
+
/*#__PURE__*/ jsx(RotateCcw, {
|
|
80
|
+
className: "h-3.5 w-3.5"
|
|
81
|
+
}),
|
|
82
|
+
retryLabel
|
|
83
|
+
]
|
|
84
|
+
})
|
|
85
|
+
]
|
|
86
|
+
}),
|
|
87
|
+
showEmpty && /*#__PURE__*/ jsxs("div", {
|
|
88
|
+
className: "py-16 text-center",
|
|
89
|
+
children: [
|
|
90
|
+
/*#__PURE__*/ jsx("div", {
|
|
91
|
+
className: "mx-auto grid h-11 w-11 place-items-center rounded-xl bg-secondary",
|
|
92
|
+
children: emptyIcon ?? /*#__PURE__*/ jsx(FileText, {
|
|
93
|
+
className: "h-5 w-5 text-muted-foreground"
|
|
94
|
+
})
|
|
95
|
+
}),
|
|
96
|
+
/*#__PURE__*/ jsx("p", {
|
|
97
|
+
className: "mt-3 text-sm font-semibold",
|
|
98
|
+
children: emptyTitle
|
|
99
|
+
}),
|
|
100
|
+
emptyDescription && /*#__PURE__*/ jsx("div", {
|
|
101
|
+
className: "mt-1 text-xs text-muted-foreground",
|
|
102
|
+
children: emptyDescription
|
|
103
|
+
})
|
|
104
|
+
]
|
|
105
|
+
}),
|
|
106
|
+
!loading && !error && !showEmpty && /*#__PURE__*/ jsx(Table, {
|
|
107
|
+
"aria-label": ariaLabel,
|
|
108
|
+
columns: columns,
|
|
109
|
+
rows: rows
|
|
110
|
+
})
|
|
111
|
+
]
|
|
112
|
+
}),
|
|
113
|
+
showFooter && (footer ?? /*#__PURE__*/ jsx("div", {
|
|
114
|
+
className: "flex items-center justify-between border-t border-border px-5 py-3 text-xs text-muted-foreground",
|
|
115
|
+
children: /*#__PURE__*/ jsxs("span", {
|
|
116
|
+
children: [
|
|
117
|
+
footerCount.label ?? "Mostrando",
|
|
118
|
+
" ",
|
|
119
|
+
/*#__PURE__*/ jsx("span", {
|
|
120
|
+
className: "font-medium text-foreground",
|
|
121
|
+
children: footerCount.shown
|
|
122
|
+
}),
|
|
123
|
+
" ",
|
|
124
|
+
"de",
|
|
125
|
+
" ",
|
|
126
|
+
/*#__PURE__*/ jsx("span", {
|
|
127
|
+
className: "font-medium text-foreground",
|
|
128
|
+
children: footerCount.total
|
|
129
|
+
})
|
|
130
|
+
]
|
|
131
|
+
})
|
|
132
|
+
}))
|
|
133
|
+
]
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { TablePane };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Legible back pill for media overlays. `SplitWorkspace` renders it by default
|
|
4
|
+
* from `backHref`/`backLabel` so a consumer never has to hand-build a readable
|
|
5
|
+
* control over dark/bright media. Token-driven surface (`bg-secondary` +
|
|
6
|
+
* `border-border`) so it reads on any background.
|
|
7
|
+
*/
|
|
8
|
+
export interface WorkspaceBackButtonProps {
|
|
9
|
+
href: string;
|
|
10
|
+
label: ReactNode;
|
|
11
|
+
/** Leading icon; defaults to a chevron. Rendered `aria-hidden` — the label names the link. */
|
|
12
|
+
icon?: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export declare function WorkspaceBackButton({ href, label, icon, }: WorkspaceBackButtonProps): import("react").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=workspace-back-button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-back-button.d.ts","sourceRoot":"","sources":["../src/workspace-back-button.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,8FAA8F;IAC9F,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,KAAK,EACL,IAA4C,GAC7C,EAAE,wBAAwB,+BAU1B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { ChevronLeft } from 'lucide-react';
|
|
4
|
+
|
|
5
|
+
function WorkspaceBackButton({ href, label, icon = /*#__PURE__*/ jsx(ChevronLeft, {
|
|
6
|
+
size: 18,
|
|
7
|
+
"aria-hidden": true
|
|
8
|
+
}) }) {
|
|
9
|
+
return /*#__PURE__*/ jsxs("a", {
|
|
10
|
+
href: href,
|
|
11
|
+
className: "inline-flex h-9 items-center gap-1 rounded-full border border-border bg-secondary pl-2 pr-3 text-sm font-medium text-secondary-foreground shadow-sm transition-colors hover:bg-border",
|
|
12
|
+
children: [
|
|
13
|
+
icon,
|
|
14
|
+
label
|
|
15
|
+
]
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { WorkspaceBackButton };
|
package/llms.txt
CHANGED
|
@@ -55,12 +55,31 @@ Filterable/searchable list shell with loading/empty/error states. Controlled:
|
|
|
55
55
|
`onSearchChange`, `loading`, `error`, `onRetry`, `isEmpty`, empty/error slots. Items go
|
|
56
56
|
in via `children`. Does NOT filter for you — filter your data (use `@lindaui/ui/search`).
|
|
57
57
|
|
|
58
|
+
### @lindaui/blocks/table-pane
|
|
59
|
+
Tabular sibling of `list-pane`: same controlled chrome (filter tabs + search +
|
|
60
|
+
loading/error/empty) around `@lindaui/ui/table`. Props: `columns: {key,label}[]`,
|
|
61
|
+
`rows: Record<string,ReactNode>[]` (each cell a ReactNode → domain chips/avatars live
|
|
62
|
+
in your app), `ariaLabel?`, the same `filters`/`activeFilter`/`onFilterChange` +
|
|
63
|
+
`searchValue`/`onSearchChange`/`searchLabel` + `loading`/`error`/`onRetry`/`isEmpty` +
|
|
64
|
+
empty slots as list-pane, plus `toolbarExtra?` (extra filter controls right of the
|
|
65
|
+
search, e.g. a `<Select>`), `footer?` (escape hatch) and `footerCount?: {shown,total,
|
|
66
|
+
label?}` (default "Mostrando X de Y"). Does NOT filter/fetch — pass already-filtered
|
|
67
|
+
`rows` and own the state.
|
|
68
|
+
|
|
58
69
|
### @lindaui/blocks/detail-panel
|
|
59
70
|
Master-detail right side: empty state + header + meta card + CTA. Controlled.
|
|
60
71
|
|
|
61
72
|
### @lindaui/blocks/split-workspace
|
|
62
73
|
Responsive split `media | panel` (controlled). Props: `media`, `panel`, `overlay?`,
|
|
63
|
-
`back?`. Two-column on desktop,
|
|
74
|
+
`backHref?`, `backLabel?` (default `"Volver"`), `back?`. Two-column on desktop,
|
|
75
|
+
stacked on mobile (uses `useIsDesktop`). Pass `backHref`/`backLabel` to get a
|
|
76
|
+
legible default back pill over any media (readability scrim + safe-area, styled
|
|
77
|
+
with `WorkspaceBackButton`); `back` is an escape hatch that wins over the pair.
|
|
78
|
+
|
|
79
|
+
### @lindaui/blocks/workspace-back-button
|
|
80
|
+
`<WorkspaceBackButton href label icon? />` — legible back pill (`<a>`, token-driven
|
|
81
|
+
`bg-secondary`/`border-border`) that reads over dark or bright media. Used by
|
|
82
|
+
`split-workspace`'s default; usable standalone. `icon` defaults to a chevron.
|
|
64
83
|
|
|
65
84
|
## Dialogs & overlays
|
|
66
85
|
|
|
@@ -73,12 +92,19 @@ box; `identity` → actor chip under the description.
|
|
|
73
92
|
Full-bleed media viewer with zoom (uses `viewer-*` tokens).
|
|
74
93
|
|
|
75
94
|
### @lindaui/blocks/recording-overlay
|
|
76
|
-
Voice-recording
|
|
95
|
+
Voice-recording UI: mic / timer / waveform / stop / cancel / error. Props include
|
|
96
|
+
`variant?: "overlay" | "inline"` (default `overlay`). `overlay` covers its container
|
|
97
|
+
on a fixed dark `viewer-*` surface (for use over media); `inline` drops the absolute
|
|
98
|
+
positioning + forced dark bg, fills its container and inherits the panel surface with
|
|
99
|
+
token-driven (legible) text. Content is identical across variants.
|
|
77
100
|
|
|
78
101
|
## Documents
|
|
79
102
|
|
|
80
103
|
### @lindaui/blocks/document-panel
|
|
81
|
-
Header + per-state body + footer. Controlled.
|
|
104
|
+
Header + per-state body + footer. Controlled. Props: `title`, `subtitle?`, `meta?`,
|
|
105
|
+
`metaPlacement?: "block"|"inline"` (default `block`), `statusBadge?`, `state`,
|
|
106
|
+
`emptyContent?`, `loadingLabel?`, `notices?`, `footer?`. `metaPlacement="inline"`
|
|
107
|
+
flows subtitle + meta on one wrapping row (`subtitle · meta`) instead of stacking.
|
|
82
108
|
|
|
83
109
|
### @lindaui/blocks/document-reader
|
|
84
110
|
Sectioned text reader.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lindaui/blocks",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Composed UI sections (auth, lists, master-detail, charts) built on @lindaui/ui — importable npm package, not a copy-paste registry.",
|
|
5
5
|
"author": "Franco Carballar <francocarballar@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -102,6 +102,14 @@
|
|
|
102
102
|
"./stats-grid": {
|
|
103
103
|
"types": "./dist/stats-grid.d.ts",
|
|
104
104
|
"import": "./dist/stats-grid.js"
|
|
105
|
+
},
|
|
106
|
+
"./workspace-back-button": {
|
|
107
|
+
"types": "./dist/workspace-back-button.d.ts",
|
|
108
|
+
"import": "./dist/workspace-back-button.js"
|
|
109
|
+
},
|
|
110
|
+
"./table-pane": {
|
|
111
|
+
"types": "./dist/table-pane.d.ts",
|
|
112
|
+
"import": "./dist/table-pane.js"
|
|
105
113
|
}
|
|
106
114
|
},
|
|
107
115
|
"files": [
|
|
@@ -138,8 +146,8 @@
|
|
|
138
146
|
"zod": "^3.23.0",
|
|
139
147
|
"@hookform/resolvers": "^3.9.0",
|
|
140
148
|
"typescript": "^6.0.3",
|
|
141
|
-
"@lindaui/tokens": "0.
|
|
142
|
-
"@lindaui/ui": "0.0
|
|
149
|
+
"@lindaui/tokens": "0.2.2",
|
|
150
|
+
"@lindaui/ui": "0.2.0"
|
|
143
151
|
},
|
|
144
152
|
"scripts": {
|
|
145
153
|
"build": "bunchee --no-dts && tsc -p tsconfig.build.json",
|