@xlabs-store/core 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/components/index.js +1 -1
  2. package/components/p-CQ2VND9-.js +1 -0
  3. package/components/p-CQQI-pRu.js +1 -0
  4. package/components/p-CkwLFDlS.js +1 -0
  5. package/components/p-CzHtwC1k.js +1 -0
  6. package/components/{p-BlvrLhyv.js → p-DqayamUz.js} +1 -1
  7. package/components/x-form-builder.js +1 -1
  8. package/components/x-icon-picker-dropdown-content.js +1 -1
  9. package/components/x-input-icon.js +1 -1
  10. package/components/x-login.js +1 -1
  11. package/components/x-table.js +1 -1
  12. package/dist/cjs/icons-BfHE2jcr.js +19261 -0
  13. package/dist/cjs/index.cjs.js +2 -2
  14. package/dist/cjs/{schema-builder-BKX4QdTc.js → schema-builder-DAwDwgIM.js} +98 -14
  15. package/dist/cjs/x-address_51.cjs.entry.js +115 -11
  16. package/dist/cjs/x-icon-picker-dropdown-content.cjs.entry.js +1 -1
  17. package/dist/collection/components/x-form-builder/services/schema/condition-builder.js +48 -6
  18. package/dist/collection/components/x-form-builder/services/schema/form-mapping.js +2 -2
  19. package/dist/collection/components/x-form-builder/utils/condition-engine.js +48 -6
  20. package/dist/collection/components/x-form-builder/x-form-builder.js +96 -6
  21. package/dist/collection/components/x-icon/icons.js +11462 -11492
  22. package/dist/collection/components/x-table/x-table.js +18 -4
  23. package/dist/esm/icons-CQ2VND9-.js +19259 -0
  24. package/dist/esm/index.js +2 -2
  25. package/dist/esm/{schema-builder-DlGEzg5B.js → schema-builder-CekbhOnD.js} +98 -14
  26. package/dist/esm/x-address_51.entry.js +115 -11
  27. package/dist/esm/x-icon-picker-dropdown-content.entry.js +1 -1
  28. package/dist/types/components/x-form-builder/types/common/field-types-enum.d.ts +1 -1
  29. package/dist/types/components/x-form-builder/types/fields/advanced-fields.d.ts +1 -0
  30. package/dist/types/components/x-form-builder/types/fields/form-field-union.d.ts +2 -2
  31. package/dist/types/components/x-form-builder/types/fields/layout-fields.d.ts +10 -1
  32. package/dist/types/components/x-form-builder/types/fields/special-input-fields.d.ts +3 -0
  33. package/dist/types/components/x-form-builder/x-form-builder.d.ts +2 -0
  34. package/dist/xlabs/index.esm.js +1 -1
  35. package/dist/xlabs/{p-45fda37b.entry.js → p-99c568fd.entry.js} +1 -1
  36. package/dist/xlabs/p-CQ2VND9-.js +1 -0
  37. package/dist/xlabs/p-CkwLFDlS.js +1 -0
  38. package/dist/xlabs/p-a4995e36.entry.js +1 -0
  39. package/dist/xlabs/xlabs.esm.js +1 -1
  40. package/package.json +1 -1
  41. package/components/p-BGNOiTqa.js +0 -1
  42. package/components/p-BgCjF74f.js +0 -1
  43. package/components/p-xf66Fag-.js +0 -1
  44. package/components/p-xzKm-BQN.js +0 -1
  45. package/dist/cjs/icons-DJ-kuboh.js +0 -19291
  46. package/dist/esm/icons-BgCjF74f.js +0 -19289
  47. package/dist/xlabs/p-239cf367.entry.js +0 -1
  48. package/dist/xlabs/p-BgCjF74f.js +0 -1
  49. package/dist/xlabs/p-xf66Fag-.js +0 -1
@@ -51,12 +51,26 @@ export function evaluateCondition(condition, formValues, context) {
51
51
  const result = (() => {
52
52
  switch (operator) {
53
53
  case 'equals':
54
+ if ((typeof actualValue === 'string' && typeof expectedValue === 'number') ||
55
+ (typeof actualValue === 'number' && typeof expectedValue === 'string')) {
56
+ return String(actualValue) === String(expectedValue);
57
+ }
54
58
  return actualValue === expectedValue;
55
59
  case 'notEquals':
60
+ if ((typeof actualValue === 'string' && typeof expectedValue === 'number') ||
61
+ (typeof actualValue === 'number' && typeof expectedValue === 'string')) {
62
+ return String(actualValue) !== String(expectedValue);
63
+ }
56
64
  return actualValue !== expectedValue;
57
65
  case 'contains':
58
66
  if (Array.isArray(actualValue)) {
59
- return actualValue.includes(expectedValue);
67
+ return actualValue.some(item => {
68
+ if ((typeof item === 'string' && typeof expectedValue === 'number') ||
69
+ (typeof item === 'number' && typeof expectedValue === 'string')) {
70
+ return String(item) === String(expectedValue);
71
+ }
72
+ return item === expectedValue;
73
+ });
60
74
  }
61
75
  if (typeof actualValue === 'string') {
62
76
  return actualValue.includes(String(expectedValue));
@@ -64,7 +78,13 @@ export function evaluateCondition(condition, formValues, context) {
64
78
  return false;
65
79
  case 'notContains':
66
80
  if (Array.isArray(actualValue)) {
67
- return !actualValue.includes(expectedValue);
81
+ return !actualValue.some(item => {
82
+ if ((typeof item === 'string' && typeof expectedValue === 'number') ||
83
+ (typeof item === 'number' && typeof expectedValue === 'string')) {
84
+ return String(item) === String(expectedValue);
85
+ }
86
+ return item === expectedValue;
87
+ });
68
88
  }
69
89
  if (typeof actualValue === 'string') {
70
90
  return !actualValue.includes(String(expectedValue));
@@ -90,24 +110,46 @@ export function evaluateCondition(condition, formValues, context) {
90
110
  return String(actualValue).endsWith(String(expectedValue));
91
111
  case 'in':
92
112
  if (Array.isArray(expectedValue)) {
93
- return expectedValue.includes(actualValue);
113
+ return expectedValue.some(item => {
114
+ if ((typeof item === 'string' && typeof actualValue === 'number') ||
115
+ (typeof item === 'number' && typeof actualValue === 'string')) {
116
+ return String(item) === String(actualValue);
117
+ }
118
+ return item === actualValue;
119
+ });
94
120
  }
95
121
  if (typeof expectedValue === 'string') {
96
122
  return expectedValue
97
123
  .split(',')
98
124
  .map(v => v.trim())
99
- .includes(String(actualValue));
125
+ .some(item => {
126
+ if (typeof actualValue === 'number') {
127
+ return item === String(actualValue);
128
+ }
129
+ return item === actualValue;
130
+ });
100
131
  }
101
132
  return false;
102
133
  case 'notIn':
103
134
  if (Array.isArray(expectedValue)) {
104
- return !expectedValue.includes(actualValue);
135
+ return !expectedValue.some(item => {
136
+ if ((typeof item === 'string' && typeof actualValue === 'number') ||
137
+ (typeof item === 'number' && typeof actualValue === 'string')) {
138
+ return String(item) === String(actualValue);
139
+ }
140
+ return item === actualValue;
141
+ });
105
142
  }
106
143
  if (typeof expectedValue === 'string') {
107
144
  return !expectedValue
108
145
  .split(',')
109
146
  .map(v => v.trim())
110
- .includes(String(actualValue));
147
+ .some(item => {
148
+ if (typeof actualValue === 'number') {
149
+ return item === String(actualValue);
150
+ }
151
+ return item === actualValue;
152
+ });
111
153
  }
112
154
  return true;
113
155
  default:
@@ -191,6 +191,15 @@ export class XFormBuilder {
191
191
  gridTemplateColumns: `repeat(${field.columns || 12}, minmax(0, 1fr))`,
192
192
  gap: `${field.gap || 15}px`,
193
193
  } }, 'elements' in field && field.elements ? this.bind(field.elements, field) : null));
194
+ const ColumnsCallback = (field) => {
195
+ const items = field.items || [];
196
+ return (h("div", { style: {
197
+ display: 'grid',
198
+ gridTemplateColumns: `repeat(12, minmax(0, 1fr))`,
199
+ gap: `${field.gap || 15}px`,
200
+ width: '100%',
201
+ } }, items.map((item) => (h("div", { style: { gridColumn: `span ${item.span || 12}` }, key: item.key }, item.elements ? this.bind(item.elements, field) : null)))));
202
+ };
194
203
  const MapsCallback = (field) => {
195
204
  const width = field.width || '100%';
196
205
  const height = field.height || 400;
@@ -455,7 +464,16 @@ export class XFormBuilder {
455
464
  dataIndex: col.dataIndex || col.key,
456
465
  slot: col.actions ? col.slot || col.key || 'action' : col.slot,
457
466
  }));
458
- return (h("x-table", { ...commonProps, columns: columns, dataSource: (field.control ? field.control.value : f.dataSource) || [], rowKey: f.rowKey || 'id', tableTitle: f.tableTitle, pagination: f.pagination, tableScroll: f.tableScroll, rowSelection: f.rowSelection, size: f.size, bordered: f.bordered, loading: f.loading, showHeader: f.showHeader, emptyText: f.emptyText, resizableColumns: f.resizableColumns, draggableColumns: f.draggableColumns, draggableRows: f.draggableRows, sticky: f.sticky, onXSelectionChange: ev => {
467
+ const controlVal = field.control?.value;
468
+ const isValArrayOfObjects = Array.isArray(controlVal) && controlVal.length > 0 && typeof controlVal[0] === 'object';
469
+ const dataSource = isValArrayOfObjects ? controlVal : (f.dataSource || []);
470
+ const rowSelection = f.rowSelection
471
+ ? {
472
+ ...f.rowSelection,
473
+ selectedRowKeys: Array.isArray(controlVal) && !isValArrayOfObjects ? controlVal : [],
474
+ }
475
+ : undefined;
476
+ return (h("x-table", { ...commonProps, columns: columns, dataSource: dataSource, rowKey: f.rowKey || 'id', tableTitle: f.tableTitle, pagination: f.pagination, tableScroll: f.tableScroll, rowSelection: rowSelection, size: f.size, bordered: f.bordered, loading: f.loading, showHeader: f.showHeader, emptyText: f.emptyText, resizableColumns: f.resizableColumns, draggableColumns: f.draggableColumns, draggableRows: f.draggableRows, sticky: f.sticky, onXSelectionChange: ev => {
459
477
  if (f.rowSelection) {
460
478
  onChange(ev.detail.selectedRowKeys);
461
479
  }
@@ -463,7 +481,7 @@ export class XFormBuilder {
463
481
  console.log('x-form-builder: Table changed:', ev.detail);
464
482
  } }, columns
465
483
  .filter(col => col.actions)
466
- .map(col => (f.dataSource || []).map((record, index) => (h("div", { slot: `${col.slot}-${index}`, style: { display: 'flex', gap: '8px' } }, (col.actions || []).map(action => {
484
+ .map(col => (dataSource || []).map((record, index) => (h("div", { slot: `${col.slot}-${index}`, style: { display: 'flex', gap: '8px' } }, (col.actions || []).map(action => {
467
485
  const button = (h("x-button", { type: action.type === 'button' ? 'primary' : 'link', size: "small", danger: action.danger, onClick: e => {
468
486
  e.stopPropagation();
469
487
  this.xTableAction.emit({
@@ -517,6 +535,29 @@ export class XFormBuilder {
517
535
  }
518
536
  return (h("x-tabs", { activeKey: activeKey, tabPlacement: f.tabPlacement || 'top', type: tabsType, editable: allowRename, hideAdd: !allowAdd, onXTabRename: onRename, onXEdit: onEdit }, items.map(item => (h("x-tab-pane", { key: item.key, paneKey: item.key, tab: item.label, disabled: item.disabled, icon: item.icon, closable: allowRemove && item.closable !== false }, this.bind(item.elements, field))))));
519
537
  };
538
+ const DynamicCallback = (field) => {
539
+ const slotName = field.meta?.slot || field.metadata?.slot || field.name;
540
+ return (h("div", { class: "x-dynamic-field-container", ...{
541
+ onXChange: (e) => {
542
+ if (field.control && e.detail && 'value' in e.detail) {
543
+ field.control.setValue(e.detail.value, { emitEvent: false });
544
+ }
545
+ }
546
+ } }, h("slot", { name: slotName }, h("div", { style: {
547
+ height: '300px',
548
+ width: '100%',
549
+ border: '1px dashed #d1d5db',
550
+ borderRadius: '8px',
551
+ backgroundColor: '#f9fafb',
552
+ display: 'flex',
553
+ flexDirection: 'column',
554
+ alignItems: 'center',
555
+ justifyContent: 'center',
556
+ color: '#9ca3af',
557
+ fontSize: '13px',
558
+ gap: '8px'
559
+ } }, h("span", { style: { fontSize: '24px' } }, "\uD83E\uDDE9"), h("span", null, "Dynamic slot \"", slotName, "\" is empty or not configured")))));
560
+ };
520
561
  return {
521
562
  'text': InputCallback,
522
563
  'input': InputCallback,
@@ -556,6 +597,9 @@ export class XFormBuilder {
556
597
  'button': ButtonCallback,
557
598
  'href': HrefCallback,
558
599
  'grid': GridCallback,
600
+ 'columns': ColumnsCallback,
601
+ 'columns-3': ColumnsCallback,
602
+ 'columns-4': ColumnsCallback,
559
603
  'table': TableCallback,
560
604
  'maps': MapsCallback,
561
605
  'panel': PanelCallback,
@@ -564,9 +608,50 @@ export class XFormBuilder {
564
608
  'qr-code': QRCodeCallback,
565
609
  'tabs': TabsCallback,
566
610
  'range-picker': DateRangeCallback,
611
+ 'dynamic': DynamicCallback,
567
612
  };
568
613
  }
569
614
  async submit(event, field) {
615
+ // Gather values from dynamic slots first
616
+ let dynamicValues = {};
617
+ let allDynamicValid = true;
618
+ let dynamicErrors = {};
619
+ if (this.builder && this.builder.form) {
620
+ const dynamicFields = Array.from(this.builder.form.mapping.values()).filter(f => f.type === 'dynamic');
621
+ for (const dField of dynamicFields) {
622
+ const slotName = dField.meta?.slot || dField.metadata?.slot || dField.name;
623
+ // Search for slotted elements in light DOM (children of this.el)
624
+ const slottedElement = Array.from(this.el.children).find(child => child.getAttribute('slot') === slotName);
625
+ if (slottedElement) {
626
+ let val = slottedElement.value;
627
+ if (val === undefined && dField.control) {
628
+ val = dField.control.value;
629
+ }
630
+ // Update internal control so built-in validators (like required) pass
631
+ if (dField.control && val !== undefined) {
632
+ dField.control.setValue(val, { emitEvent: false });
633
+ }
634
+ // Check if it has a validate method
635
+ if (typeof slottedElement.validate === 'function') {
636
+ const res = await slottedElement.validate(val);
637
+ if (res) {
638
+ allDynamicValid = false;
639
+ dynamicErrors[dField.name] = res;
640
+ slottedElement.validationState = {
641
+ status: 'invalid',
642
+ errorMessage: typeof res === 'object' ? Object.values(res)[0] : 'Invalid',
643
+ errors: res
644
+ };
645
+ }
646
+ else {
647
+ slottedElement.validationState = { status: 'valid', errors: null, errorMessage: '' };
648
+ }
649
+ }
650
+ // Merge value
651
+ dynamicValues[dField.name] = val;
652
+ }
653
+ }
654
+ }
570
655
  // Validate all mapped controls (both sync and async) first to ensure errors are updated
571
656
  if (this.builder && this.builder.form) {
572
657
  for (const [_key, fld] of Array.from(this.builder.form.mapping.entries())) {
@@ -591,9 +676,9 @@ export class XFormBuilder {
591
676
  }
592
677
  }
593
678
  }
594
- if (this.builder.form.valid && allCaptchaValid) {
679
+ if (this.builder.form.valid && allCaptchaValid && allDynamicValid) {
595
680
  this.formSubmit.emit({
596
- value: this.builder.form.value,
681
+ value: { ...this.builder.form.value, ...dynamicValues },
597
682
  builder: this.builder,
598
683
  event: event,
599
684
  field,
@@ -615,7 +700,7 @@ export class XFormBuilder {
615
700
  this.formError.emit({
616
701
  builder: this.builder,
617
702
  event: event,
618
- errors: this.builder.form.errors,
703
+ errors: { ...this.builder.form.errors, ...dynamicErrors },
619
704
  });
620
705
  }
621
706
  }
@@ -678,7 +763,8 @@ export class XFormBuilder {
678
763
  const control = field.control;
679
764
  if (control && this.builder && control.touched) {
680
765
  commonProps.status = undefined;
681
- if (control.invalid) {
766
+ // Bỏ qua hiển thị lỗi nội bộ của x-form-builder cho các trường dynamic vì client tự quản lý
767
+ if (control.invalid && field.type !== 'dynamic') {
682
768
  commonProps.status = 'error';
683
769
  const errors = control.errors ?? {};
684
770
  const messages = this.getMessageValidator(field, errors);
@@ -727,6 +813,10 @@ export class XFormBuilder {
727
813
  componentWillLoad() {
728
814
  this.asyncBuilderForm(true);
729
815
  }
816
+ componentDidUpdate() {
817
+ }
818
+ disconnectedCallback() {
819
+ }
730
820
  handleValueChange() {
731
821
  if (this._isInternalChange)
732
822
  return;