pixelon 0.3.77 → 0.3.79
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/components/atoms/lumi/FieldValue/FieldValue.d.ts +15 -0
- package/dist/components/atoms/lumi/FieldValue/index.d.ts +2 -0
- package/dist/components/atoms/lumi/FieldValue/types.d.ts +10 -0
- package/dist/components/atoms/lumi/Icon/Icon.d.ts +1 -0
- package/dist/components/molecules/chat/StructuredContent/components/ReactiveCrud/ChatLinkCell.d.ts +20 -0
- package/dist/components/molecules/chat/StructuredContent/components/ReactiveCrud/optionsLoader.d.ts +2 -1
- package/dist/components/molecules/chat/StructuredContent/components/ReactiveCrud/types.d.ts +6 -0
- package/dist/components/molecules/lumi/Drawer/Drawer.d.ts +8 -0
- package/dist/components/molecules/lumi/RecordCard/RecordCard.d.ts +14 -0
- package/dist/components/molecules/lumi/RecordCard/index.d.ts +2 -0
- package/dist/components/molecules/lumi/RecordCard/types.d.ts +16 -0
- package/dist/components/molecules/lumi/ScrollToEnd/ScrollToEnd.d.ts +21 -0
- package/dist/components/molecules/lumi/ScrollToEnd/index.d.ts +2 -0
- package/dist/components/templates/lumi/Crud/CardList.d.ts +34 -0
- package/dist/components/templates/lumi/Crud/Crud.d.ts +1 -1
- package/dist/components/templates/lumi/Crud/ScrollToEnd.d.ts +18 -0
- package/dist/components/templates/lumi/Crud/helpers/fieldValue.d.ts +12 -0
- package/dist/components/templates/lumi/Crud/types.d.ts +25 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +566 -276
- package/dist/index.js +567 -275
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +1 -1
- package/src/styles/index.scss +4 -0
package/dist/index.js
CHANGED
|
@@ -4008,13 +4008,13 @@ function resolveVariable(template, formValues, fieldStates) {
|
|
|
4008
4008
|
}
|
|
4009
4009
|
return "";
|
|
4010
4010
|
}
|
|
4011
|
-
function resolveBody(obj, formValues, fieldStates) {
|
|
4011
|
+
function resolveBody$1(obj, formValues, fieldStates) {
|
|
4012
4012
|
if (typeof obj === "string") return resolveVariable(obj, formValues, fieldStates);
|
|
4013
|
-
if (Array.isArray(obj)) return obj.map((item) => resolveBody(item, formValues, fieldStates));
|
|
4013
|
+
if (Array.isArray(obj)) return obj.map((item) => resolveBody$1(item, formValues, fieldStates));
|
|
4014
4014
|
if (obj !== null && typeof obj === "object") {
|
|
4015
4015
|
const resolved = {};
|
|
4016
4016
|
for (const [key, value] of Object.entries(obj)) {
|
|
4017
|
-
resolved[key] = resolveBody(value, formValues, fieldStates);
|
|
4017
|
+
resolved[key] = resolveBody$1(value, formValues, fieldStates);
|
|
4018
4018
|
}
|
|
4019
4019
|
return resolved;
|
|
4020
4020
|
}
|
|
@@ -4064,7 +4064,7 @@ const CostSummaryField = ({
|
|
|
4064
4064
|
return;
|
|
4065
4065
|
}
|
|
4066
4066
|
fetchedRef.current = true;
|
|
4067
|
-
const body = resolveBody(field.endpoint.body || {}, values, fieldStates);
|
|
4067
|
+
const body = resolveBody$1(field.endpoint.body || {}, values, fieldStates);
|
|
4068
4068
|
setLoading(true);
|
|
4069
4069
|
setError("");
|
|
4070
4070
|
fetchViaEventBus(eventBus, field.endpoint.service, field.endpoint.url, field.endpoint.method, body).then((data) => {
|
|
@@ -4518,7 +4518,7 @@ function useReactiveEndpoints({ fields, fieldStates, setFieldState, eventBus, ti
|
|
|
4518
4518
|
setFieldState(field.name, { loading: true, error: null });
|
|
4519
4519
|
const startTime = Date.now();
|
|
4520
4520
|
try {
|
|
4521
|
-
const resolvedBody = field.endpoint.body ? resolveBody(field.endpoint.body, formValues, fieldStates) : void 0;
|
|
4521
|
+
const resolvedBody = field.endpoint.body ? resolveBody$1(field.endpoint.body, formValues, fieldStates) : void 0;
|
|
4522
4522
|
const params = field.endpoint.params ? resolveParams(field.endpoint.params, formValues, fieldStates) : {};
|
|
4523
4523
|
const requestBody = resolvedBody ?? (Object.keys(params).length > 0 ? params : void 0);
|
|
4524
4524
|
if (eventBus) {
|
|
@@ -4793,7 +4793,7 @@ function useReactiveForm(props) {
|
|
|
4793
4793
|
const handleSubmit = async () => {
|
|
4794
4794
|
if (isSubmitting) return;
|
|
4795
4795
|
setIsSubmitting(true);
|
|
4796
|
-
const resolvedPayload = resolveBody(submit.payload_map, values, fieldStates);
|
|
4796
|
+
const resolvedPayload = resolveBody$1(submit.payload_map, values, fieldStates);
|
|
4797
4797
|
if (eventBus) {
|
|
4798
4798
|
try {
|
|
4799
4799
|
const data = await fetchViaEventBus(
|
|
@@ -5753,6 +5753,7 @@ const LUMI_ICON_TYPES = {
|
|
|
5753
5753
|
MENU: "menu",
|
|
5754
5754
|
ARROW_UP: "arrow-up",
|
|
5755
5755
|
ARROW_RIGHT: "arrow-right",
|
|
5756
|
+
ARROW_LEFT: "arrow-left",
|
|
5756
5757
|
// Iconos para Servicios
|
|
5757
5758
|
BUILDING: "building",
|
|
5758
5759
|
MAP_PIN: "map-pin",
|
|
@@ -6424,6 +6425,24 @@ const ArrowRightIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
|
6424
6425
|
]
|
|
6425
6426
|
}
|
|
6426
6427
|
);
|
|
6428
|
+
const ArrowLeftIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6429
|
+
"svg",
|
|
6430
|
+
{
|
|
6431
|
+
width: "16",
|
|
6432
|
+
height: "16",
|
|
6433
|
+
viewBox: "0 0 24 24",
|
|
6434
|
+
fill: "none",
|
|
6435
|
+
stroke: "currentColor",
|
|
6436
|
+
strokeWidth: "2",
|
|
6437
|
+
strokeLinecap: "round",
|
|
6438
|
+
strokeLinejoin: "round",
|
|
6439
|
+
...props,
|
|
6440
|
+
children: [
|
|
6441
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
|
|
6442
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "12 19 5 12 12 5" })
|
|
6443
|
+
]
|
|
6444
|
+
}
|
|
6445
|
+
);
|
|
6427
6446
|
const BuildingIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6428
6447
|
"svg",
|
|
6429
6448
|
{
|
|
@@ -6565,6 +6584,7 @@ const lumiIconMap = {
|
|
|
6565
6584
|
[LUMI_ICON_TYPES.MENU]: MenuIcon,
|
|
6566
6585
|
[LUMI_ICON_TYPES.ARROW_UP]: ArrowUpIcon,
|
|
6567
6586
|
[LUMI_ICON_TYPES.ARROW_RIGHT]: ArrowRightIcon,
|
|
6587
|
+
[LUMI_ICON_TYPES.ARROW_LEFT]: ArrowLeftIcon,
|
|
6568
6588
|
// Iconos para Servicios
|
|
6569
6589
|
[LUMI_ICON_TYPES.BUILDING]: BuildingIcon,
|
|
6570
6590
|
[LUMI_ICON_TYPES.MAP_PIN]: MapPinIcon,
|
|
@@ -10886,6 +10906,7 @@ const Drawer = ({
|
|
|
10886
10906
|
size = DRAWER_SIZES.RESPONSIVE,
|
|
10887
10907
|
fixedSize = 400,
|
|
10888
10908
|
responsivePercentage = 80,
|
|
10909
|
+
mobileSheet = false,
|
|
10889
10910
|
title,
|
|
10890
10911
|
headerExtra,
|
|
10891
10912
|
showCloseButton = true,
|
|
@@ -10968,11 +10989,13 @@ const Drawer = ({
|
|
|
10968
10989
|
`${COMPONENT_PREFIX}drawer--${size}`,
|
|
10969
10990
|
isOpen && `${COMPONENT_PREFIX}drawer--open`,
|
|
10970
10991
|
isMobile && `${COMPONENT_PREFIX}drawer--mobile`,
|
|
10992
|
+
mobileSheet && `${COMPONENT_PREFIX}drawer--sheet`,
|
|
10971
10993
|
className
|
|
10972
10994
|
].filter(Boolean).join(" ");
|
|
10973
10995
|
const overlayClasses = [
|
|
10974
10996
|
`${COMPONENT_PREFIX}drawer-overlay`,
|
|
10975
|
-
isOpen && showOverlay && `${COMPONENT_PREFIX}drawer-overlay--visible
|
|
10997
|
+
isOpen && showOverlay && `${COMPONENT_PREFIX}drawer-overlay--visible`,
|
|
10998
|
+
mobileSheet && `${COMPONENT_PREFIX}drawer-overlay--sheet`
|
|
10976
10999
|
].filter(Boolean).join(" ");
|
|
10977
11000
|
const getDrawerStyles = () => {
|
|
10978
11001
|
if (isMobile) {
|
|
@@ -11036,6 +11059,7 @@ const Drawer = ({
|
|
|
11036
11059
|
variant: "ghost",
|
|
11037
11060
|
onClick: onClose,
|
|
11038
11061
|
"aria-label": "Cerrar drawer",
|
|
11062
|
+
className: `${COMPONENT_PREFIX}drawer__close`,
|
|
11039
11063
|
icon: /* @__PURE__ */ jsxRuntime.jsx(Icon, { type: LUMI_ICON_TYPES.CLOSE, size: "medium" })
|
|
11040
11064
|
}
|
|
11041
11065
|
)
|
|
@@ -13079,36 +13103,45 @@ const Badge = ({
|
|
|
13079
13103
|
};
|
|
13080
13104
|
Badge.displayName = "LumiBadge";
|
|
13081
13105
|
|
|
13106
|
+
function fieldOptions(field) {
|
|
13107
|
+
return field.uiProps?.options;
|
|
13108
|
+
}
|
|
13109
|
+
function renderFieldValue(field, row) {
|
|
13110
|
+
const value = row[field.key];
|
|
13111
|
+
const options = fieldOptions(field);
|
|
13112
|
+
const opt = options?.find((o) => String(o.value) === String(value));
|
|
13113
|
+
if (field.moleculeType === "BADGE") {
|
|
13114
|
+
if (value == null || value === "") return null;
|
|
13115
|
+
return React.createElement(Badge, { color: opt?.color, children: opt?.label ?? String(value) });
|
|
13116
|
+
}
|
|
13117
|
+
if (field.moleculeType === "INPUT_CURRENCY") {
|
|
13118
|
+
if (value == null || value === "") return null;
|
|
13119
|
+
const cp = field.uiProps ?? {};
|
|
13120
|
+
return React.createElement(CurrencyDisplay, {
|
|
13121
|
+
value,
|
|
13122
|
+
showCode: cp.showCode ?? true,
|
|
13123
|
+
showSymbol: cp.showSymbol ?? true,
|
|
13124
|
+
currency: cp.currency ?? { decimalPlaces: 0 },
|
|
13125
|
+
align: field.align ?? "right",
|
|
13126
|
+
size: cp.size ?? "md"
|
|
13127
|
+
});
|
|
13128
|
+
}
|
|
13129
|
+
if (field.formatValue) return field.formatValue(value, row);
|
|
13130
|
+
if (opt) return opt.label;
|
|
13131
|
+
return value;
|
|
13132
|
+
}
|
|
13133
|
+
function hasFieldValue(field, row) {
|
|
13134
|
+
const value = row[field.key];
|
|
13135
|
+
return value != null && value !== "";
|
|
13136
|
+
}
|
|
13137
|
+
|
|
13082
13138
|
function mapFieldsToTableColumns(fields) {
|
|
13083
13139
|
return fields.filter((field) => field.showInTable !== false).map((field) => {
|
|
13084
13140
|
let width = field.columnWidth;
|
|
13085
13141
|
if (field.fixed && typeof field.columnWidth === "number") {
|
|
13086
13142
|
width = `${field.columnWidth}px`;
|
|
13087
13143
|
}
|
|
13088
|
-
const
|
|
13089
|
-
const build = (row) => {
|
|
13090
|
-
const value = row[field.key];
|
|
13091
|
-
const opt = options?.find((o) => String(o.value) === String(value));
|
|
13092
|
-
if (field.moleculeType === "BADGE") {
|
|
13093
|
-
if (value == null || value === "") return null;
|
|
13094
|
-
return React.createElement(Badge, { color: opt?.color, children: opt?.label ?? String(value) });
|
|
13095
|
-
}
|
|
13096
|
-
if (field.moleculeType === "INPUT_CURRENCY") {
|
|
13097
|
-
if (value == null || value === "") return null;
|
|
13098
|
-
const cp = field.uiProps ?? {};
|
|
13099
|
-
return React.createElement(CurrencyDisplay, {
|
|
13100
|
-
value,
|
|
13101
|
-
showCode: cp.showCode ?? true,
|
|
13102
|
-
showSymbol: cp.showSymbol ?? true,
|
|
13103
|
-
currency: cp.currency ?? { decimalPlaces: 0 },
|
|
13104
|
-
align: field.align ?? "right",
|
|
13105
|
-
size: cp.size ?? "md"
|
|
13106
|
-
});
|
|
13107
|
-
}
|
|
13108
|
-
if (field.formatValue) return field.formatValue(value, row);
|
|
13109
|
-
if (opt) return opt.label;
|
|
13110
|
-
return value;
|
|
13111
|
-
};
|
|
13144
|
+
const build = (row) => renderFieldValue(field, row);
|
|
13112
13145
|
return {
|
|
13113
13146
|
key: field.key,
|
|
13114
13147
|
title: field.label,
|
|
@@ -13139,10 +13172,201 @@ function mapFieldsToFormFields(fields, mode) {
|
|
|
13139
13172
|
}));
|
|
13140
13173
|
}
|
|
13141
13174
|
|
|
13175
|
+
const CLASS$e = `${COMPONENT_PREFIX}field-value`;
|
|
13176
|
+
const FieldValue = ({
|
|
13177
|
+
label,
|
|
13178
|
+
children,
|
|
13179
|
+
layout = "inline",
|
|
13180
|
+
className
|
|
13181
|
+
}) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: [CLASS$e, `${CLASS$e}--${layout}`, className].filter(Boolean).join(" "), children: [
|
|
13182
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$e}__label`, children: label }),
|
|
13183
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$e}__value`, children })
|
|
13184
|
+
] });
|
|
13185
|
+
FieldValue.displayName = "FieldValue";
|
|
13186
|
+
|
|
13187
|
+
const CLASS$d = `${COMPONENT_PREFIX}record-card`;
|
|
13188
|
+
const RecordCard = ({
|
|
13189
|
+
title,
|
|
13190
|
+
summary,
|
|
13191
|
+
children,
|
|
13192
|
+
actions,
|
|
13193
|
+
open = false,
|
|
13194
|
+
onToggle,
|
|
13195
|
+
ariaLabel,
|
|
13196
|
+
className
|
|
13197
|
+
}) => {
|
|
13198
|
+
const cuerpoId = React.useId();
|
|
13199
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: [CLASS$d, open ? `${CLASS$d}--open` : "", className].filter(Boolean).join(" "), children: [
|
|
13200
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
13201
|
+
"button",
|
|
13202
|
+
{
|
|
13203
|
+
type: "button",
|
|
13204
|
+
className: `${CLASS$d}__header`,
|
|
13205
|
+
"aria-expanded": open,
|
|
13206
|
+
"aria-controls": cuerpoId,
|
|
13207
|
+
"aria-label": ariaLabel,
|
|
13208
|
+
onClick: onToggle,
|
|
13209
|
+
children: [
|
|
13210
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$d}__heading`, children: [
|
|
13211
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$d}__title`, children: title }),
|
|
13212
|
+
summary && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$d}__summary`, children: summary })
|
|
13213
|
+
] }),
|
|
13214
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13215
|
+
Icon,
|
|
13216
|
+
{
|
|
13217
|
+
type: open ? "chevron-up" : "chevron-down",
|
|
13218
|
+
width: 18,
|
|
13219
|
+
height: 18,
|
|
13220
|
+
className: `${CLASS$d}__chevron`,
|
|
13221
|
+
"aria-hidden": true
|
|
13222
|
+
}
|
|
13223
|
+
)
|
|
13224
|
+
]
|
|
13225
|
+
}
|
|
13226
|
+
),
|
|
13227
|
+
open && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$d}__body`, id: cuerpoId, children: [
|
|
13228
|
+
children,
|
|
13229
|
+
actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$d}__actions`, children: actions })
|
|
13230
|
+
] })
|
|
13231
|
+
] });
|
|
13232
|
+
};
|
|
13233
|
+
RecordCard.displayName = "RecordCard";
|
|
13234
|
+
|
|
13235
|
+
const CLASS$c = `${COMPONENT_PREFIX}crud-cards`;
|
|
13236
|
+
function summaryFields(fields) {
|
|
13237
|
+
const visibles = fields.filter((f) => f.showInTable !== false);
|
|
13238
|
+
const marcados = visibles.filter((f) => f.summary);
|
|
13239
|
+
return marcados.length > 0 ? marcados : visibles.slice(0, 3);
|
|
13240
|
+
}
|
|
13241
|
+
function CardList({
|
|
13242
|
+
fields,
|
|
13243
|
+
rows,
|
|
13244
|
+
rowKey,
|
|
13245
|
+
buildOptions,
|
|
13246
|
+
loading = false,
|
|
13247
|
+
emptyText = "No hay registros"
|
|
13248
|
+
}) {
|
|
13249
|
+
const [abierta, setAbierta] = React.useState(null);
|
|
13250
|
+
const resumen = summaryFields(fields);
|
|
13251
|
+
const claveResumen = new Set(resumen.map((f) => f.key));
|
|
13252
|
+
const cuerpo = fields.filter((f) => f.showInTable !== false && !claveResumen.has(f.key));
|
|
13253
|
+
if (loading && rows.length === 0) {
|
|
13254
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$c}__estado`, children: "Cargando..." });
|
|
13255
|
+
}
|
|
13256
|
+
if (rows.length === 0) {
|
|
13257
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$c}__estado`, children: emptyText });
|
|
13258
|
+
}
|
|
13259
|
+
const [principal, ...secundarios] = resumen;
|
|
13260
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: CLASS$c, children: rows.map((row) => {
|
|
13261
|
+
const key = rowKey(row);
|
|
13262
|
+
const opciones = buildOptions?.(row) ?? [];
|
|
13263
|
+
const titulo = principal ? renderFieldValue(principal, row) : key;
|
|
13264
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13265
|
+
RecordCard,
|
|
13266
|
+
{
|
|
13267
|
+
open: abierta === key,
|
|
13268
|
+
onToggle: () => setAbierta((actual) => actual === key ? null : key),
|
|
13269
|
+
ariaLabel: principal ? `${principal.label}: ${String(row[principal.key] ?? "")}` : void 0,
|
|
13270
|
+
title: titulo,
|
|
13271
|
+
summary: secundarios.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: secundarios.map((f) => /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: renderFieldValue(f, row) }, f.key)) }) : void 0,
|
|
13272
|
+
actions: opciones.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: opciones.map((o) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13273
|
+
"button",
|
|
13274
|
+
{
|
|
13275
|
+
type: "button",
|
|
13276
|
+
className: [
|
|
13277
|
+
`${CLASS$c}__accion`,
|
|
13278
|
+
o.disabled && o.disabledReason ? "is-con-motivo" : ""
|
|
13279
|
+
].filter(Boolean).join(" "),
|
|
13280
|
+
disabled: o.disabled,
|
|
13281
|
+
onClick: () => void o.onClick(),
|
|
13282
|
+
children: [
|
|
13283
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: o.label }),
|
|
13284
|
+
o.disabled && o.disabledReason && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$c}__motivo`, children: o.disabledReason })
|
|
13285
|
+
]
|
|
13286
|
+
},
|
|
13287
|
+
o.label
|
|
13288
|
+
)) }) : void 0,
|
|
13289
|
+
children: cuerpo.map(
|
|
13290
|
+
(f) => hasFieldValue(f, row) ? /* @__PURE__ */ jsxRuntime.jsx(FieldValue, { label: f.label, children: renderFieldValue(f, row) }, f.key) : null
|
|
13291
|
+
)
|
|
13292
|
+
},
|
|
13293
|
+
key
|
|
13294
|
+
);
|
|
13295
|
+
}) });
|
|
13296
|
+
}
|
|
13297
|
+
CardList.displayName = "CardList";
|
|
13298
|
+
|
|
13299
|
+
const CLASS$b = `${COMPONENT_PREFIX}crud-scroll-end`;
|
|
13300
|
+
const MARGEN = 24;
|
|
13301
|
+
const SELECTOR_CRUD = `.${COMPONENT_PREFIX}table-container, .${COMPONENT_PREFIX}crud-cards`;
|
|
13302
|
+
const ScrollToEnd = ({
|
|
13303
|
+
hostRef,
|
|
13304
|
+
selector = SELECTOR_CRUD,
|
|
13305
|
+
dep,
|
|
13306
|
+
label = "Ir al final de la lista"
|
|
13307
|
+
}) => {
|
|
13308
|
+
const [visible, setVisible] = React.useState(false);
|
|
13309
|
+
const scrollerRef = React.useRef(null);
|
|
13310
|
+
React.useEffect(() => {
|
|
13311
|
+
const host = hostRef.current;
|
|
13312
|
+
if (!host) return;
|
|
13313
|
+
const scroller = host.querySelector(selector) ?? host;
|
|
13314
|
+
scrollerRef.current = scroller;
|
|
13315
|
+
if (!scroller) {
|
|
13316
|
+
setVisible(false);
|
|
13317
|
+
return;
|
|
13318
|
+
}
|
|
13319
|
+
const revisar = () => {
|
|
13320
|
+
const s = scrollerRef.current;
|
|
13321
|
+
if (!s) return;
|
|
13322
|
+
setVisible(s.scrollHeight - s.clientHeight - s.scrollTop > MARGEN);
|
|
13323
|
+
};
|
|
13324
|
+
revisar();
|
|
13325
|
+
scroller.addEventListener("scroll", revisar, { passive: true });
|
|
13326
|
+
let observador;
|
|
13327
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
13328
|
+
observador = new ResizeObserver(revisar);
|
|
13329
|
+
observador.observe(scroller);
|
|
13330
|
+
if (scroller.firstElementChild) observador.observe(scroller.firstElementChild);
|
|
13331
|
+
}
|
|
13332
|
+
return () => {
|
|
13333
|
+
scroller.removeEventListener("scroll", revisar);
|
|
13334
|
+
observador?.disconnect();
|
|
13335
|
+
};
|
|
13336
|
+
}, [hostRef, selector, dep]);
|
|
13337
|
+
const alFinal = React.useCallback(() => {
|
|
13338
|
+
const s = scrollerRef.current;
|
|
13339
|
+
if (!s) return;
|
|
13340
|
+
s.scrollTo({ top: s.scrollHeight, behavior: "smooth" });
|
|
13341
|
+
}, []);
|
|
13342
|
+
if (!visible) return null;
|
|
13343
|
+
return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: CLASS$b, onClick: alFinal, "aria-label": label, title: label, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { type: "chevron-down", width: 18, height: 18, "aria-hidden": true }) });
|
|
13344
|
+
};
|
|
13345
|
+
ScrollToEnd.displayName = "ScrollToEnd";
|
|
13346
|
+
|
|
13142
13347
|
function calculateTotalPages(totalRecords, limit) {
|
|
13143
13348
|
return Math.ceil(totalRecords / limit);
|
|
13144
13349
|
}
|
|
13145
13350
|
|
|
13351
|
+
const useAnchoPropio = () => {
|
|
13352
|
+
const ref = React.useRef(null);
|
|
13353
|
+
const [ancho, setAncho] = React.useState(null);
|
|
13354
|
+
React.useEffect(() => {
|
|
13355
|
+
const nodo = ref.current;
|
|
13356
|
+
if (!nodo) return;
|
|
13357
|
+
if (typeof ResizeObserver === "undefined") {
|
|
13358
|
+
setAncho(nodo.getBoundingClientRect().width);
|
|
13359
|
+
return;
|
|
13360
|
+
}
|
|
13361
|
+
const observador = new ResizeObserver((entradas) => {
|
|
13362
|
+
const w = entradas[0]?.contentRect.width;
|
|
13363
|
+
if (typeof w === "number") setAncho(w);
|
|
13364
|
+
});
|
|
13365
|
+
observador.observe(nodo);
|
|
13366
|
+
return () => observador.disconnect();
|
|
13367
|
+
}, []);
|
|
13368
|
+
return [ref, ancho];
|
|
13369
|
+
};
|
|
13146
13370
|
const useIsMobile = () => {
|
|
13147
13371
|
const [isMobile, setIsMobile] = React.useState(false);
|
|
13148
13372
|
React.useEffect(() => {
|
|
@@ -13182,6 +13406,8 @@ function Crud({
|
|
|
13182
13406
|
defaultFilters,
|
|
13183
13407
|
tableHeight,
|
|
13184
13408
|
tableScroll,
|
|
13409
|
+
layout = "auto",
|
|
13410
|
+
cardsBelow = 768,
|
|
13185
13411
|
hidePagination = false,
|
|
13186
13412
|
formDrawerWidth = "80%",
|
|
13187
13413
|
formColumns = 2,
|
|
@@ -13286,6 +13512,69 @@ function Crud({
|
|
|
13286
13512
|
}
|
|
13287
13513
|
return columns;
|
|
13288
13514
|
}, [renderByFields, isMobile, tableScroll?.x]);
|
|
13515
|
+
const buildRowOptions = React.useCallback((row) => {
|
|
13516
|
+
const menuOptions = [];
|
|
13517
|
+
if (rowActionTypes.includes("edit") && !disabledActions?.edit && onEdit) {
|
|
13518
|
+
menuOptions.push({
|
|
13519
|
+
label: labels?.editButton || "Editar",
|
|
13520
|
+
icon: "edit",
|
|
13521
|
+
onClick: () => {
|
|
13522
|
+
openFormDrawer("edit", row);
|
|
13523
|
+
}
|
|
13524
|
+
});
|
|
13525
|
+
}
|
|
13526
|
+
if (rowActionTypes.includes("delete") && !disabledActions?.delete && onDelete) {
|
|
13527
|
+
menuOptions.push({
|
|
13528
|
+
label: labels?.deleteButton || "Eliminar",
|
|
13529
|
+
icon: "trash",
|
|
13530
|
+
onClick: () => {
|
|
13531
|
+
openConfirmDrawer("delete", void 0, [row]);
|
|
13532
|
+
}
|
|
13533
|
+
});
|
|
13534
|
+
}
|
|
13535
|
+
if (rowActionTypes.includes("view") && !disabledActions?.view) {
|
|
13536
|
+
menuOptions.push({
|
|
13537
|
+
label: labels?.viewButton || "Ver",
|
|
13538
|
+
icon: "eye",
|
|
13539
|
+
onClick: async () => {
|
|
13540
|
+
if (onView) {
|
|
13541
|
+
await onView([row]);
|
|
13542
|
+
}
|
|
13543
|
+
openFormDrawer("view", row);
|
|
13544
|
+
}
|
|
13545
|
+
});
|
|
13546
|
+
}
|
|
13547
|
+
rowActions?.forEach((action) => {
|
|
13548
|
+
if (action.show && !action.show(row)) return;
|
|
13549
|
+
menuOptions.push({
|
|
13550
|
+
label: action.label,
|
|
13551
|
+
icon: action.icon,
|
|
13552
|
+
onClick: () => {
|
|
13553
|
+
if (action.drawerId) {
|
|
13554
|
+
openCustomDrawer(action.drawerId, row);
|
|
13555
|
+
}
|
|
13556
|
+
if (action.onClick) {
|
|
13557
|
+
action.onClick(row);
|
|
13558
|
+
}
|
|
13559
|
+
},
|
|
13560
|
+
disabled: action.disabled ? action.disabled(row) : false,
|
|
13561
|
+
// SPEC-090 T3 — una acción apagada sin motivo es indistinguible de una rota.
|
|
13562
|
+
disabledReason: action.disabledReason?.(row)
|
|
13563
|
+
});
|
|
13564
|
+
});
|
|
13565
|
+
return menuOptions;
|
|
13566
|
+
}, [
|
|
13567
|
+
rowActionTypes,
|
|
13568
|
+
disabledActions,
|
|
13569
|
+
onEdit,
|
|
13570
|
+
onDelete,
|
|
13571
|
+
onView,
|
|
13572
|
+
labels,
|
|
13573
|
+
openFormDrawer,
|
|
13574
|
+
openConfirmDrawer,
|
|
13575
|
+
openCustomDrawer,
|
|
13576
|
+
rowActions
|
|
13577
|
+
]);
|
|
13289
13578
|
const tableColumns = React.useMemo(() => {
|
|
13290
13579
|
if (!showRowActions) return baseTableColumns;
|
|
13291
13580
|
const actionsColumn = {
|
|
@@ -13297,55 +13586,7 @@ function Crud({
|
|
|
13297
13586
|
cellType: "CHILDREN",
|
|
13298
13587
|
dataSource: {
|
|
13299
13588
|
build: (row) => {
|
|
13300
|
-
const menuOptions =
|
|
13301
|
-
if (rowActionTypes.includes("edit") && !disabledActions?.edit && onEdit) {
|
|
13302
|
-
menuOptions.push({
|
|
13303
|
-
label: labels?.editButton || "Editar",
|
|
13304
|
-
icon: "edit",
|
|
13305
|
-
onClick: () => {
|
|
13306
|
-
openFormDrawer("edit", row);
|
|
13307
|
-
}
|
|
13308
|
-
});
|
|
13309
|
-
}
|
|
13310
|
-
if (rowActionTypes.includes("delete") && !disabledActions?.delete && onDelete) {
|
|
13311
|
-
menuOptions.push({
|
|
13312
|
-
label: labels?.deleteButton || "Eliminar",
|
|
13313
|
-
icon: "trash",
|
|
13314
|
-
onClick: () => {
|
|
13315
|
-
openConfirmDrawer("delete", void 0, [row]);
|
|
13316
|
-
}
|
|
13317
|
-
});
|
|
13318
|
-
}
|
|
13319
|
-
if (rowActionTypes.includes("view") && !disabledActions?.view) {
|
|
13320
|
-
menuOptions.push({
|
|
13321
|
-
label: labels?.viewButton || "Ver",
|
|
13322
|
-
icon: "eye",
|
|
13323
|
-
onClick: async () => {
|
|
13324
|
-
if (onView) {
|
|
13325
|
-
await onView([row]);
|
|
13326
|
-
}
|
|
13327
|
-
openFormDrawer("view", row);
|
|
13328
|
-
}
|
|
13329
|
-
});
|
|
13330
|
-
}
|
|
13331
|
-
rowActions?.forEach((action) => {
|
|
13332
|
-
if (action.show && !action.show(row)) return;
|
|
13333
|
-
menuOptions.push({
|
|
13334
|
-
label: action.label,
|
|
13335
|
-
icon: action.icon,
|
|
13336
|
-
onClick: () => {
|
|
13337
|
-
if (action.drawerId) {
|
|
13338
|
-
openCustomDrawer(action.drawerId, row);
|
|
13339
|
-
}
|
|
13340
|
-
if (action.onClick) {
|
|
13341
|
-
action.onClick(row);
|
|
13342
|
-
}
|
|
13343
|
-
},
|
|
13344
|
-
disabled: action.disabled ? action.disabled(row) : false,
|
|
13345
|
-
// SPEC-090 T3 — una acción apagada sin motivo es indistinguible de una rota.
|
|
13346
|
-
disabledReason: action.disabledReason?.(row)
|
|
13347
|
-
});
|
|
13348
|
-
});
|
|
13589
|
+
const menuOptions = buildRowOptions(row);
|
|
13349
13590
|
if (menuOptions.length === 0) return null;
|
|
13350
13591
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", width: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13351
13592
|
DropdownMenu,
|
|
@@ -13368,20 +13609,7 @@ function Crud({
|
|
|
13368
13609
|
}
|
|
13369
13610
|
};
|
|
13370
13611
|
return [...baseTableColumns, actionsColumn];
|
|
13371
|
-
}, [
|
|
13372
|
-
baseTableColumns,
|
|
13373
|
-
showRowActions,
|
|
13374
|
-
rowActionTypes,
|
|
13375
|
-
disabledActions,
|
|
13376
|
-
labels,
|
|
13377
|
-
onEdit,
|
|
13378
|
-
onDelete,
|
|
13379
|
-
onView,
|
|
13380
|
-
rowActions,
|
|
13381
|
-
openFormDrawer,
|
|
13382
|
-
openConfirmDrawer,
|
|
13383
|
-
openCustomDrawer
|
|
13384
|
-
]);
|
|
13612
|
+
}, [baseTableColumns, showRowActions, buildRowOptions]);
|
|
13385
13613
|
const formFields = React.useMemo(() => {
|
|
13386
13614
|
return mapFieldsToFormFields(renderByFields, formMode);
|
|
13387
13615
|
}, [renderByFields, formMode]);
|
|
@@ -13578,6 +13806,10 @@ function Crud({
|
|
|
13578
13806
|
return "\xBFEst\xE1 seguro que desea realizar esta acci\xF3n?";
|
|
13579
13807
|
}
|
|
13580
13808
|
};
|
|
13809
|
+
const [refContenedor, anchoPropio] = useAnchoPropio();
|
|
13810
|
+
const enTarjetas = layout === "cards" || // Mientras no se ha medido (`null`) se mantiene la tabla: pintar tarjetas y saltar a tabla un
|
|
13811
|
+
// instante después es el parpadeo que se acaba de quitar en otro sitio.
|
|
13812
|
+
layout === "auto" && anchoPropio !== null && anchoPropio < cardsBelow;
|
|
13581
13813
|
const crudClasses = [
|
|
13582
13814
|
`${COMPONENT_PREFIX}crud`,
|
|
13583
13815
|
loading && `${COMPONENT_PREFIX}crud--loading`,
|
|
@@ -13594,24 +13826,43 @@ function Crud({
|
|
|
13594
13826
|
showLabels: false
|
|
13595
13827
|
}
|
|
13596
13828
|
) }),
|
|
13597
|
-
!formOnly && /* @__PURE__ */ jsxRuntime.
|
|
13598
|
-
|
|
13829
|
+
!formOnly && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13830
|
+
"div",
|
|
13599
13831
|
{
|
|
13600
|
-
|
|
13601
|
-
|
|
13602
|
-
|
|
13603
|
-
|
|
13604
|
-
|
|
13605
|
-
|
|
13606
|
-
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13832
|
+
className: `${COMPONENT_PREFIX}crud__data${enTarjetas ? ` ${COMPONENT_PREFIX}crud__data--cards` : ""}`,
|
|
13833
|
+
children: [
|
|
13834
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `${COMPONENT_PREFIX}crud__table`, ref: refContenedor, children: enTarjetas ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
13835
|
+
CardList,
|
|
13836
|
+
{
|
|
13837
|
+
fields: renderByFields,
|
|
13838
|
+
rows: dataSource,
|
|
13839
|
+
rowKey: getRowKey,
|
|
13840
|
+
buildOptions: showRowActions ? buildRowOptions : void 0,
|
|
13841
|
+
loading,
|
|
13842
|
+
emptyText: labels?.emptyText
|
|
13843
|
+
}
|
|
13844
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
13845
|
+
Table$1,
|
|
13846
|
+
{
|
|
13847
|
+
dataSource,
|
|
13848
|
+
columns: tableColumns,
|
|
13849
|
+
selectable: showActionBar && actionBarMode === "full",
|
|
13850
|
+
selectedRowKeys: selectedKeys,
|
|
13851
|
+
onSelectionChange: handleSelectionChange,
|
|
13852
|
+
rowKey: getRowKey,
|
|
13853
|
+
loading,
|
|
13854
|
+
height: tableHeight,
|
|
13855
|
+
scroll: tableScroll,
|
|
13856
|
+
compact: size === "small",
|
|
13857
|
+
bordered: true,
|
|
13858
|
+
hoverable: true,
|
|
13859
|
+
emptyText: labels?.emptyText
|
|
13860
|
+
}
|
|
13861
|
+
) }),
|
|
13862
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollToEnd, { hostRef: refContenedor, dep: `${enTarjetas}:${dataSource.length}:${loading}` })
|
|
13863
|
+
]
|
|
13613
13864
|
}
|
|
13614
|
-
)
|
|
13865
|
+
),
|
|
13615
13866
|
!formOnly && !filters.all_data && !hidePagination && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${COMPONENT_PREFIX}crud__pagination`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13616
13867
|
Pagination,
|
|
13617
13868
|
{
|
|
@@ -13676,6 +13927,7 @@ function Crud({
|
|
|
13676
13927
|
position: "right",
|
|
13677
13928
|
size: "responsive",
|
|
13678
13929
|
responsivePercentage: 30,
|
|
13930
|
+
mobileSheet: true,
|
|
13679
13931
|
className: `${COMPONENT_PREFIX}crud__confirm-drawer`,
|
|
13680
13932
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${COMPONENT_PREFIX}crud__confirm-content`, children: [
|
|
13681
13933
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `${COMPONENT_PREFIX}crud__confirm-message`, children: getConfirmMessage() }),
|
|
@@ -13724,6 +13976,60 @@ function Crud({
|
|
|
13724
13976
|
}
|
|
13725
13977
|
Crud.displayName = "Crud";
|
|
13726
13978
|
|
|
13979
|
+
const CLASS$a = "px-chat-reactive-crud__chat-link";
|
|
13980
|
+
function Burbuja() {
|
|
13981
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13982
|
+
"svg",
|
|
13983
|
+
{
|
|
13984
|
+
width: 18,
|
|
13985
|
+
height: 18,
|
|
13986
|
+
viewBox: "0 0 24 24",
|
|
13987
|
+
fill: "none",
|
|
13988
|
+
stroke: "currentColor",
|
|
13989
|
+
strokeWidth: 2,
|
|
13990
|
+
strokeLinecap: "round",
|
|
13991
|
+
strokeLinejoin: "round",
|
|
13992
|
+
"aria-hidden": true,
|
|
13993
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
|
|
13994
|
+
}
|
|
13995
|
+
);
|
|
13996
|
+
}
|
|
13997
|
+
const ChatLinkCell = ({
|
|
13998
|
+
targets,
|
|
13999
|
+
eventBus
|
|
14000
|
+
}) => {
|
|
14001
|
+
if (targets.length === 0) return null;
|
|
14002
|
+
const abrir = (id) => eventBus?.emit(CHAT_EVENT.OPEN_CHAT, { chatId: id, closed: false });
|
|
14003
|
+
if (targets.length === 1) {
|
|
14004
|
+
const t = targets[0];
|
|
14005
|
+
const texto = t.label ? `Abrir chat ${t.label}` : "Abrir chat";
|
|
14006
|
+
return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: CLASS$a, "aria-label": texto, title: texto, onClick: () => abrir(t.id), children: /* @__PURE__ */ jsxRuntime.jsx(Burbuja, {}) });
|
|
14007
|
+
}
|
|
14008
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14009
|
+
DropdownMenu,
|
|
14010
|
+
{
|
|
14011
|
+
options: targets.map((t) => ({
|
|
14012
|
+
label: t.label ?? "Chat",
|
|
14013
|
+
icon: "message-square",
|
|
14014
|
+
onClick: () => abrir(t.id)
|
|
14015
|
+
})),
|
|
14016
|
+
trigger: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14017
|
+
"button",
|
|
14018
|
+
{
|
|
14019
|
+
type: "button",
|
|
14020
|
+
className: CLASS$a,
|
|
14021
|
+
"aria-label": `Abrir chat (${targets.length} conversaciones)`,
|
|
14022
|
+
title: "Abrir chat",
|
|
14023
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Burbuja, {})
|
|
14024
|
+
}
|
|
14025
|
+
),
|
|
14026
|
+
position: "bottom-left",
|
|
14027
|
+
usePortal: true
|
|
14028
|
+
}
|
|
14029
|
+
);
|
|
14030
|
+
};
|
|
14031
|
+
ChatLinkCell.displayName = "ChatLinkCell";
|
|
14032
|
+
|
|
13727
14033
|
function buildCrudYupSchema(fields) {
|
|
13728
14034
|
const shape = {};
|
|
13729
14035
|
for (const f of fields) {
|
|
@@ -13804,8 +14110,21 @@ function unwrap$3(raw) {
|
|
|
13804
14110
|
}
|
|
13805
14111
|
return raw;
|
|
13806
14112
|
}
|
|
13807
|
-
|
|
13808
|
-
|
|
14113
|
+
function resolveBody(body, ctx) {
|
|
14114
|
+
if (!body) return {};
|
|
14115
|
+
if (!ctx) return body;
|
|
14116
|
+
return Object.fromEntries(
|
|
14117
|
+
Object.entries(body).map(([k, v]) => {
|
|
14118
|
+
if (typeof v === "string" && v.startsWith("$")) {
|
|
14119
|
+
const key = v.slice(1);
|
|
14120
|
+
return [k, key in ctx ? ctx[key] : v];
|
|
14121
|
+
}
|
|
14122
|
+
return [k, v];
|
|
14123
|
+
})
|
|
14124
|
+
);
|
|
14125
|
+
}
|
|
14126
|
+
async function loadOptions(eventBus, ep, ctx) {
|
|
14127
|
+
const raw = await fetchViaEventBus(eventBus, ep.service, ep.url, ep.method, resolveBody(ep.body, ctx));
|
|
13809
14128
|
let data = unwrap$3(raw);
|
|
13810
14129
|
if (ep.response_path && data && typeof data === "object" && !Array.isArray(data)) {
|
|
13811
14130
|
data = data[ep.response_path];
|
|
@@ -13881,7 +14200,7 @@ function useReactiveCrud(config, eventBus) {
|
|
|
13881
14200
|
const loadList = React.useCallback(async () => {
|
|
13882
14201
|
if (!eventBus) return;
|
|
13883
14202
|
const myReq = ++reqIdRef.current;
|
|
13884
|
-
setState((s) =>
|
|
14203
|
+
setState((s) => s.rows.length === 0 ? { ...s, loading: true, error: null } : { ...s, error: null });
|
|
13885
14204
|
try {
|
|
13886
14205
|
const { service, url, method } = config.data.list;
|
|
13887
14206
|
const raw = await fetchViaEventBus(eventBus, service, url, method, {
|
|
@@ -14132,7 +14451,7 @@ function ActionFormDrawer({ action, row, idField, eventBus, onExecute, onClose }
|
|
|
14132
14451
|
void Promise.all(
|
|
14133
14452
|
toLoad.map(async (f) => {
|
|
14134
14453
|
try {
|
|
14135
|
-
const opts = await loadOptions(eventBus, f.optionsEndpoint);
|
|
14454
|
+
const opts = await loadOptions(eventBus, f.optionsEndpoint, { ...row, id: row[idField] });
|
|
14136
14455
|
return [f.name, opts];
|
|
14137
14456
|
} catch {
|
|
14138
14457
|
return [f.name, []];
|
|
@@ -14821,6 +15140,7 @@ function unwrap$1(raw) {
|
|
|
14821
15140
|
}
|
|
14822
15141
|
return raw;
|
|
14823
15142
|
}
|
|
15143
|
+
const DETALLE_OCULTOS = /* @__PURE__ */ new Set(["LOCATION", "CHAT_LINK", "FILE"]);
|
|
14824
15144
|
function DetailDrawer({ row, config, eventBus, onClose, loadedOptions }) {
|
|
14825
15145
|
const detail = config.detail;
|
|
14826
15146
|
const [files, setFiles] = React.useState([]);
|
|
@@ -14919,7 +15239,7 @@ function DetailDrawer({ row, config, eventBus, onClose, loadedOptions }) {
|
|
|
14919
15239
|
}
|
|
14920
15240
|
};
|
|
14921
15241
|
return /* @__PURE__ */ jsxRuntime.jsx(Drawer$1, { isOpen: true, onClose, title, placement: "right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-reactive-crud-detail", children: [
|
|
14922
|
-
/* @__PURE__ */ jsxRuntime.jsx("dl", { className: "px-chat-reactive-crud-detail__fields", children: config.fields.map((f) => {
|
|
15242
|
+
/* @__PURE__ */ jsxRuntime.jsx("dl", { className: "px-chat-reactive-crud-detail__fields", children: config.fields.filter((f) => !DETALLE_OCULTOS.has(f.moleculeType)).map((f) => {
|
|
14923
15243
|
const { node, copyText } = renderField(f);
|
|
14924
15244
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-reactive-crud-detail__row", children: [
|
|
14925
15245
|
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "px-chat-reactive-crud-detail__label", children: f.label }),
|
|
@@ -15581,35 +15901,13 @@ const LocationField = ({
|
|
|
15581
15901
|
};
|
|
15582
15902
|
LocationField.displayName = "LocationField";
|
|
15583
15903
|
|
|
15584
|
-
function chatLinkButton(id, eventBus, label) {
|
|
15585
|
-
return React.createElement(
|
|
15586
|
-
"button",
|
|
15587
|
-
{
|
|
15588
|
-
key: label ?? id,
|
|
15589
|
-
type: "button",
|
|
15590
|
-
className: "px-chat-reactive-crud__chat-link",
|
|
15591
|
-
"aria-label": label ? `Abrir chat ${label}` : "Abrir chat",
|
|
15592
|
-
title: label ?? "Abrir chat",
|
|
15593
|
-
onClick: () => eventBus?.emit(CHAT_EVENT.OPEN_CHAT, { chatId: id, closed: false })
|
|
15594
|
-
},
|
|
15595
|
-
React.createElement(
|
|
15596
|
-
"svg",
|
|
15597
|
-
{ width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" },
|
|
15598
|
-
React.createElement("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
|
|
15599
|
-
),
|
|
15600
|
-
label ? React.createElement("span", { className: "px-chat-reactive-crud__chat-link-label" }, label) : null
|
|
15601
|
-
);
|
|
15602
|
-
}
|
|
15603
15904
|
function chatLinkFormatter(field, eventBus) {
|
|
15604
15905
|
const sources = field.chats;
|
|
15605
15906
|
return (value, row) => {
|
|
15606
15907
|
const r = row;
|
|
15607
|
-
|
|
15608
|
-
|
|
15609
|
-
|
|
15610
|
-
}
|
|
15611
|
-
const id = value != null && value !== "" ? String(value) : "";
|
|
15612
|
-
return id ? chatLinkButton(id, eventBus) : null;
|
|
15908
|
+
const targets = sources?.length ? sources.map((s) => ({ id: r ? r[s.field] : void 0, label: s.label })).filter((s) => s.id != null && s.id !== "").map((s) => ({ id: String(s.id), label: s.label })) : value != null && value !== "" ? [{ id: String(value) }] : [];
|
|
15909
|
+
if (!targets.length) return null;
|
|
15910
|
+
return React.createElement(ChatLinkCell, { targets, eventBus });
|
|
15613
15911
|
};
|
|
15614
15912
|
}
|
|
15615
15913
|
function toRenderField(f, loaded, eventBus, mapsApiKey) {
|
|
@@ -15648,6 +15946,8 @@ function toRenderField(f, loaded, eventBus, mapsApiKey) {
|
|
|
15648
15946
|
// FILE/CHAT_LINK solo son columnas → INPUT (el render lo define formatValue/build).
|
|
15649
15947
|
moleculeType: f.moleculeType === "FILE" || isChatLink ? "INPUT" : f.moleculeType,
|
|
15650
15948
|
showInTable: f.showInTable,
|
|
15949
|
+
summary: f.summary,
|
|
15950
|
+
// SPEC-093
|
|
15651
15951
|
showInForm: f.showInForm,
|
|
15652
15952
|
showInModes: f.showInModes,
|
|
15653
15953
|
required: f.required,
|
|
@@ -15777,6 +16077,8 @@ function ReactiveCrud({ config, eventBus, autoOpenCreate, prefill, onCreated, on
|
|
|
15777
16077
|
loading: crud.loading,
|
|
15778
16078
|
filters: { skip: crud.skip, limit: crud.pageSize, all_data: false, filters: crud.filters },
|
|
15779
16079
|
tableScroll: config.tableScroll,
|
|
16080
|
+
layout: config.layout,
|
|
16081
|
+
cardsBelow: config.cardsBelow,
|
|
15780
16082
|
validationSchema,
|
|
15781
16083
|
getRowKey: (row) => String(row[config.idField]),
|
|
15782
16084
|
onCreate: config.data.create ? async (rows) => {
|
|
@@ -16046,12 +16348,18 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus
|
|
|
16046
16348
|
"button",
|
|
16047
16349
|
{
|
|
16048
16350
|
type: "button",
|
|
16049
|
-
className:
|
|
16351
|
+
className: [
|
|
16352
|
+
"px-chat-crud-item__action",
|
|
16353
|
+
a.intent === "danger" ? "is-danger" : "",
|
|
16354
|
+
disabled && a.disabledReason ? "is-con-motivo" : ""
|
|
16355
|
+
].filter(Boolean).join(" "),
|
|
16050
16356
|
disabled,
|
|
16051
|
-
title: disabled ? a.disabledReason : void 0,
|
|
16052
16357
|
onClick: () => a.form ? setActiveAction({ action: a, row }) : crud.runEndpoints(a.endpoints ?? [a.endpoint], { ...row, id: row[config.idField] }),
|
|
16053
16358
|
children: [
|
|
16054
|
-
/* @__PURE__ */ jsxRuntime.
|
|
16359
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-chat-crud-item__action-texts", children: [
|
|
16360
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: a.label }),
|
|
16361
|
+
disabled && a.disabledReason && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-crud-item__action-reason", children: a.disabledReason })
|
|
16362
|
+
] }),
|
|
16055
16363
|
done && /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: "check-circle", width: 18, height: 18, className: "px-chat-crud-item__done", "aria-label": "Hecho" })
|
|
16056
16364
|
]
|
|
16057
16365
|
},
|
|
@@ -16686,6 +16994,7 @@ function ChatNavigator({ config, eventBus }) {
|
|
|
16686
16994
|
React.useEffect(() => {
|
|
16687
16995
|
void load();
|
|
16688
16996
|
}, [load]);
|
|
16997
|
+
const listaRef = React.useRef(null);
|
|
16689
16998
|
const loadRef = React.useRef(load);
|
|
16690
16999
|
loadRef.current = load;
|
|
16691
17000
|
React.useEffect(() => {
|
|
@@ -16733,8 +17042,6 @@ function ChatNavigator({ config, eventBus }) {
|
|
|
16733
17042
|
};
|
|
16734
17043
|
const page = Math.floor(skip / pageSize) + 1;
|
|
16735
17044
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
16736
|
-
const canPrev = skip > 0;
|
|
16737
|
-
const canNext = skip + pageSize < total;
|
|
16738
17045
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-chat-navigator", children: [
|
|
16739
17046
|
config.search && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-chat-navigator__search", children: [
|
|
16740
17047
|
/* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "px-chat-chat-navigator__search-icon", children: [
|
|
@@ -16814,143 +17121,126 @@ function ChatNavigator({ config, eventBus }) {
|
|
|
16814
17121
|
loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-chat-navigator__state", children: "Cargando conversaciones\u2026" }),
|
|
16815
17122
|
error && !loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-chat-navigator__state px-chat-chat-navigator__state--error", children: error }),
|
|
16816
17123
|
!loading && !error && items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-chat-navigator__state", children: labels.emptyText ?? "Sin conversaciones" }),
|
|
16817
|
-
/* @__PURE__ */ jsxRuntime.
|
|
16818
|
-
|
|
16819
|
-
|
|
16820
|
-
|
|
16821
|
-
|
|
16822
|
-
|
|
16823
|
-
|
|
16824
|
-
|
|
16825
|
-
|
|
16826
|
-
e
|
|
16827
|
-
|
|
16828
|
-
|
|
16829
|
-
|
|
16830
|
-
|
|
16831
|
-
|
|
16832
|
-
autoFocus: true,
|
|
16833
|
-
className: "px-chat-chat-navigator__rename-input",
|
|
16834
|
-
value: renameValue,
|
|
16835
|
-
onChange: (e) => setRenameValue(e.target.value),
|
|
16836
|
-
onBlur: () => void submitRename(item.id),
|
|
16837
|
-
"aria-label": labels.renameTitle ?? "Nuevo t\xEDtulo"
|
|
16838
|
-
}
|
|
16839
|
-
)
|
|
16840
|
-
}
|
|
16841
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "px-chat-chat-navigator__open", onClick: () => open(item), children: [
|
|
16842
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-chat-chat-navigator__title", children: [
|
|
16843
|
-
displayTitle,
|
|
16844
|
-
item.unread_proactive_count && item.unread_proactive_count >= 1 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
16845
|
-
"span",
|
|
16846
|
-
{
|
|
16847
|
-
className: "px-chat-chat-navigator__badge-count",
|
|
16848
|
-
"aria-label": `${item.unread_proactive_count} mensajes nuevos sin leer`,
|
|
16849
|
-
title: `${item.unread_proactive_count} sin leer`,
|
|
16850
|
-
children: item.unread_proactive_count >= 100 ? "100+" : item.unread_proactive_count
|
|
16851
|
-
}
|
|
16852
|
-
) : null
|
|
16853
|
-
] }),
|
|
16854
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-chat-chat-navigator__meta", children: [
|
|
16855
|
-
item.agent_name ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-chat-navigator__agent", children: item.agent_name }) : null,
|
|
16856
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-chat-navigator__time", children: relativeTime(item.updated_date) }),
|
|
16857
|
-
(() => {
|
|
16858
|
-
const opt = item.rol_code ? (config.originActorOptions ?? []).find((o) => o.value === item.rol_code) : void 0;
|
|
16859
|
-
if (!opt) return null;
|
|
16860
|
-
const c = opt.color;
|
|
16861
|
-
const nameField = config.originActorNameField;
|
|
16862
|
-
const allyName = nameField ? item[nameField] : void 0;
|
|
16863
|
-
const label = allyName ? String(allyName) : opt.label;
|
|
16864
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16865
|
-
"span",
|
|
16866
|
-
{
|
|
16867
|
-
className: "px-chat-chat-navigator__origin-badge",
|
|
16868
|
-
style: c ? { color: c, background: `${c}22`, borderColor: `${c}55` } : void 0,
|
|
16869
|
-
title: label,
|
|
16870
|
-
children: label
|
|
16871
|
-
}
|
|
16872
|
-
);
|
|
16873
|
-
})(),
|
|
16874
|
-
(() => {
|
|
16875
|
-
const field = config.tagField;
|
|
16876
|
-
if (!field) return null;
|
|
16877
|
-
const value = item[field];
|
|
16878
|
-
if (!value) return null;
|
|
16879
|
-
const opt = (config.tagOptions ?? []).find((o) => o.value === String(value));
|
|
16880
|
-
if (!opt) return null;
|
|
16881
|
-
const c = opt.color;
|
|
16882
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16883
|
-
"span",
|
|
17124
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-chat-navigator__list-wrap", ref: listaRef, children: [
|
|
17125
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "px-chat-chat-navigator__list", children: items.map((item) => {
|
|
17126
|
+
const isRenaming = renamingId === item.id;
|
|
17127
|
+
const displayTitle = item.title?.trim() || fallbackTitle(item);
|
|
17128
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "px-chat-chat-navigator__item", children: [
|
|
17129
|
+
isRenaming ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17130
|
+
"form",
|
|
17131
|
+
{
|
|
17132
|
+
className: "px-chat-chat-navigator__rename",
|
|
17133
|
+
onSubmit: (e) => {
|
|
17134
|
+
e.preventDefault();
|
|
17135
|
+
void submitRename(item.id);
|
|
17136
|
+
},
|
|
17137
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17138
|
+
"input",
|
|
16884
17139
|
{
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
17140
|
+
autoFocus: true,
|
|
17141
|
+
className: "px-chat-chat-navigator__rename-input",
|
|
17142
|
+
value: renameValue,
|
|
17143
|
+
onChange: (e) => setRenameValue(e.target.value),
|
|
17144
|
+
onBlur: () => void submitRename(item.id),
|
|
17145
|
+
"aria-label": labels.renameTitle ?? "Nuevo t\xEDtulo"
|
|
16889
17146
|
}
|
|
16890
|
-
)
|
|
16891
|
-
}
|
|
16892
|
-
|
|
16893
|
-
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
const c = opt?.color;
|
|
16897
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17147
|
+
)
|
|
17148
|
+
}
|
|
17149
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "px-chat-chat-navigator__open", onClick: () => open(item), children: [
|
|
17150
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-chat-chat-navigator__title", children: [
|
|
17151
|
+
displayTitle,
|
|
17152
|
+
item.unread_proactive_count && item.unread_proactive_count >= 1 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
16898
17153
|
"span",
|
|
16899
17154
|
{
|
|
16900
|
-
className: "px-chat-chat-
|
|
16901
|
-
|
|
16902
|
-
|
|
17155
|
+
className: "px-chat-chat-navigator__badge-count",
|
|
17156
|
+
"aria-label": `${item.unread_proactive_count} mensajes nuevos sin leer`,
|
|
17157
|
+
title: `${item.unread_proactive_count} sin leer`,
|
|
17158
|
+
children: item.unread_proactive_count >= 100 ? "100+" : item.unread_proactive_count
|
|
16903
17159
|
}
|
|
16904
|
-
)
|
|
16905
|
-
})
|
|
16906
|
-
|
|
16907
|
-
|
|
16908
|
-
|
|
16909
|
-
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
|
|
16914
|
-
|
|
16915
|
-
|
|
16916
|
-
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
|
|
17160
|
+
) : null
|
|
17161
|
+
] }),
|
|
17162
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-chat-chat-navigator__meta", children: [
|
|
17163
|
+
item.agent_name ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-chat-navigator__agent", children: item.agent_name }) : null,
|
|
17164
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-chat-navigator__time", children: relativeTime(item.updated_date) }),
|
|
17165
|
+
(() => {
|
|
17166
|
+
const opt = item.rol_code ? (config.originActorOptions ?? []).find((o) => o.value === item.rol_code) : void 0;
|
|
17167
|
+
if (!opt) return null;
|
|
17168
|
+
const c = opt.color;
|
|
17169
|
+
const nameField = config.originActorNameField;
|
|
17170
|
+
const allyName = nameField ? item[nameField] : void 0;
|
|
17171
|
+
const label = allyName ? String(allyName) : opt.label;
|
|
17172
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17173
|
+
"span",
|
|
17174
|
+
{
|
|
17175
|
+
className: "px-chat-chat-navigator__origin-badge",
|
|
17176
|
+
style: c ? { color: c, background: `${c}22`, borderColor: `${c}55` } : void 0,
|
|
17177
|
+
title: label,
|
|
17178
|
+
children: label
|
|
17179
|
+
}
|
|
17180
|
+
);
|
|
17181
|
+
})(),
|
|
17182
|
+
(() => {
|
|
17183
|
+
const field = config.tagField;
|
|
17184
|
+
if (!field) return null;
|
|
17185
|
+
const value = item[field];
|
|
17186
|
+
if (!value) return null;
|
|
17187
|
+
const opt = (config.tagOptions ?? []).find((o) => o.value === String(value));
|
|
17188
|
+
if (!opt) return null;
|
|
17189
|
+
const c = opt.color;
|
|
17190
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17191
|
+
"span",
|
|
17192
|
+
{
|
|
17193
|
+
className: "px-chat-chat-navigator__origin-badge",
|
|
17194
|
+
style: c ? { color: c, background: `${c}22`, borderColor: `${c}55` } : void 0,
|
|
17195
|
+
title: opt.label,
|
|
17196
|
+
children: opt.label
|
|
17197
|
+
}
|
|
17198
|
+
);
|
|
17199
|
+
})(),
|
|
17200
|
+
item.service_status ? (() => {
|
|
17201
|
+
const opt = (config.serviceStatusOptions ?? []).find(
|
|
17202
|
+
(o) => o.value === item.service_status
|
|
17203
|
+
);
|
|
17204
|
+
const c = opt?.color;
|
|
17205
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17206
|
+
"span",
|
|
17207
|
+
{
|
|
17208
|
+
className: "px-chat-chat-navigator__service-badge",
|
|
17209
|
+
style: c ? { color: c, background: `${c}22`, borderColor: `${c}55` } : void 0,
|
|
17210
|
+
children: opt?.label ?? item.service_status
|
|
17211
|
+
}
|
|
17212
|
+
);
|
|
17213
|
+
})() : null,
|
|
17214
|
+
item.closed ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-chat-navigator__badge", children: labels.closedBadge ?? "Cerrado" }) : null
|
|
16920
17215
|
] })
|
|
16921
|
-
}
|
|
16922
|
-
|
|
16923
|
-
|
|
16924
|
-
|
|
16925
|
-
|
|
16926
|
-
|
|
16927
|
-
|
|
16928
|
-
|
|
16929
|
-
|
|
16930
|
-
|
|
16931
|
-
|
|
16932
|
-
|
|
16933
|
-
|
|
16934
|
-
|
|
16935
|
-
|
|
16936
|
-
|
|
16937
|
-
|
|
16938
|
-
|
|
16939
|
-
" / ",
|
|
16940
|
-
totalPages
|
|
16941
|
-
] }),
|
|
16942
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16943
|
-
"button",
|
|
16944
|
-
{
|
|
16945
|
-
type: "button",
|
|
16946
|
-
className: "px-chat-chat-navigator__pager-btn",
|
|
16947
|
-
disabled: !canNext,
|
|
16948
|
-
onClick: () => setSkip(skip + pageSize),
|
|
16949
|
-
"aria-label": "P\xE1gina siguiente",
|
|
16950
|
-
children: "\u203A"
|
|
16951
|
-
}
|
|
16952
|
-
)
|
|
17216
|
+
] }),
|
|
17217
|
+
config.data.rename && !isRenaming && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17218
|
+
"button",
|
|
17219
|
+
{
|
|
17220
|
+
type: "button",
|
|
17221
|
+
className: "px-chat-chat-navigator__rename-btn",
|
|
17222
|
+
"aria-label": "Renombrar",
|
|
17223
|
+
title: "Renombrar",
|
|
17224
|
+
onClick: () => startRename(item),
|
|
17225
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
17226
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 20h9" }),
|
|
17227
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z" })
|
|
17228
|
+
] })
|
|
17229
|
+
}
|
|
17230
|
+
)
|
|
17231
|
+
] }, item.id);
|
|
17232
|
+
}) }),
|
|
17233
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollToEnd, { hostRef: listaRef, selector: ".px-chat-chat-navigator__list", dep: `${items.length}:${loading}` })
|
|
16953
17234
|
] }),
|
|
17235
|
+
total > pageSize && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-chat-navigator__pager", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17236
|
+
Pagination,
|
|
17237
|
+
{
|
|
17238
|
+
current: page,
|
|
17239
|
+
total: totalPages,
|
|
17240
|
+
onChange: (p) => setSkip((p - 1) * pageSize),
|
|
17241
|
+
showTotal: false
|
|
17242
|
+
}
|
|
17243
|
+
) }),
|
|
16954
17244
|
config.advancedFilters?.length ? /* @__PURE__ */ jsxRuntime.jsx(Drawer$1, { isOpen: advOpen, onClose: () => setAdvOpen(false), title: "Filtros avanzados", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
16955
17245
|
Filter,
|
|
16956
17246
|
{
|
|
@@ -24355,6 +24645,7 @@ exports.LumiDateInput = DateInput$1;
|
|
|
24355
24645
|
exports.LumiDrawer = Drawer;
|
|
24356
24646
|
exports.LumiDropdownMenu = DropdownMenu;
|
|
24357
24647
|
exports.LumiDynamicForm = DynamicForm;
|
|
24648
|
+
exports.LumiFieldValue = FieldValue;
|
|
24358
24649
|
exports.LumiFilter = Filter;
|
|
24359
24650
|
exports.LumiFilterRow = FilterRow;
|
|
24360
24651
|
exports.LumiFormCheckbox = Checkbox;
|
|
@@ -24373,6 +24664,7 @@ exports.LumiNotification = Notification;
|
|
|
24373
24664
|
exports.LumiPagination = Pagination;
|
|
24374
24665
|
exports.LumiPopover = Popover;
|
|
24375
24666
|
exports.LumiQRCode = QRCode;
|
|
24667
|
+
exports.LumiRecordCard = RecordCard;
|
|
24376
24668
|
exports.LumiSelect = Select$1;
|
|
24377
24669
|
exports.LumiStepIndicator = StepIndicator;
|
|
24378
24670
|
exports.LumiStepper = Stepper;
|