coles-solid-library 0.4.7 → 0.4.9
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/USAGE.html +31 -1
- package/dist/components/Checkbox/checkbox.d.ts +3 -0
- package/dist/components/Chip/Chip.d.ts +1 -1
- package/dist/components/Form/form.d.ts +5 -3
- package/dist/components/Form/formGroup.d.ts +16 -5
- package/dist/components/Form/formHelp/formArray.d.ts +76 -72
- package/dist/components/Form/formHelp/models.d.ts +0 -1
- package/dist/components/Form/useDirectFormBinding.d.ts +40 -0
- package/dist/components/Input/Input.d.ts +3 -0
- package/dist/components/Input/inputV2.d.ts +3 -0
- package/dist/components/Radio/radioGroup.d.ts +3 -0
- package/dist/components/Select/select.component.d.ts +3 -0
- package/dist/components/Select/selectContext.d.ts +2 -0
- package/dist/components/TextArea/TextArea.d.ts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +650 -390
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1493,13 +1493,329 @@ var css_248z$e = "@charset \"UTF-8\";\n.input-module_input__-LMoi {\n width: 10
|
|
|
1493
1493
|
var styles$9 = {"input":"input-module_input__-LMoi","disabled":"input-module_disabled__40ZHw","inFormField":"input-module_inFormField__kk-PD","transparent":"input-module_transparent__aXcGX"};
|
|
1494
1494
|
styleInject(css_248z$e);
|
|
1495
1495
|
|
|
1496
|
+
/**
|
|
1497
|
+
* A class that encapsulates an array of FormGroup instances along with optional array-level validation.
|
|
1498
|
+
*
|
|
1499
|
+
* @template T - An object type representing the shape of a single form group's value.
|
|
1500
|
+
*/
|
|
1501
|
+
class FormArray {
|
|
1502
|
+
/**
|
|
1503
|
+
* Array-level validators that validate the entire array of form group values.
|
|
1504
|
+
* @private
|
|
1505
|
+
*/
|
|
1506
|
+
internalArrayValidation;
|
|
1507
|
+
/**
|
|
1508
|
+
* The FormGroup instances managed by this array.
|
|
1509
|
+
* @private
|
|
1510
|
+
*/
|
|
1511
|
+
groups;
|
|
1512
|
+
/**
|
|
1513
|
+
* Solid store setter for the groups array.
|
|
1514
|
+
* @private
|
|
1515
|
+
*/
|
|
1516
|
+
setGroups;
|
|
1517
|
+
/**
|
|
1518
|
+
* Array-level errors (from array-level validators only).
|
|
1519
|
+
* Per-item errors live in each FormGroup.
|
|
1520
|
+
* @private
|
|
1521
|
+
*/
|
|
1522
|
+
arrayErrors = [];
|
|
1523
|
+
/**
|
|
1524
|
+
* Snapshot of initial groups for reset.
|
|
1525
|
+
* @private
|
|
1526
|
+
*/
|
|
1527
|
+
_initialGroups;
|
|
1528
|
+
/**
|
|
1529
|
+
* Creates an instance of FormArray.
|
|
1530
|
+
*
|
|
1531
|
+
* @param groups - An array of FormGroup instances representing the initial items.
|
|
1532
|
+
* @param arrayValidators - Optional array-level validators (e.g., min/max item count).
|
|
1533
|
+
*/
|
|
1534
|
+
constructor(groups = [], arrayValidators = []) {
|
|
1535
|
+
const [storeGroups, setStoreGroups] = createStore([...groups]);
|
|
1536
|
+
this.groups = storeGroups;
|
|
1537
|
+
this.setGroups = setStoreGroups;
|
|
1538
|
+
this.internalArrayValidation = arrayValidators;
|
|
1539
|
+
this._initialGroups = [...groups];
|
|
1540
|
+
}
|
|
1541
|
+
/**
|
|
1542
|
+
* Returns the number of items in the array.
|
|
1543
|
+
*/
|
|
1544
|
+
get length() {
|
|
1545
|
+
return this.groups.length;
|
|
1546
|
+
}
|
|
1547
|
+
/**
|
|
1548
|
+
* Returns true if any validator (array-level or within any group) exists matching the provided errKey.
|
|
1549
|
+
* If no errKey provided, returns true when any validator exists at all.
|
|
1550
|
+
*/
|
|
1551
|
+
hasAnyValidator(errKey) {
|
|
1552
|
+
if (!errKey) {
|
|
1553
|
+
return this.internalArrayValidation.length > 0 || this.groups.some(g => g.hasAnyValidator());
|
|
1554
|
+
}
|
|
1555
|
+
const inArray = this.internalArrayValidation.some(v => v.errKey === errKey);
|
|
1556
|
+
if (inArray) return true;
|
|
1557
|
+
return this.groups.some(g => g.hasAnyValidator(errKey));
|
|
1558
|
+
}
|
|
1559
|
+
/**
|
|
1560
|
+
* Resets the array to its initial groups and clears array-level errors.
|
|
1561
|
+
* Each initial FormGroup is reset to its own initial state.
|
|
1562
|
+
*/
|
|
1563
|
+
reset() {
|
|
1564
|
+
this._initialGroups.forEach(g => g.reset());
|
|
1565
|
+
this.setGroups(() => [...this._initialGroups]);
|
|
1566
|
+
this.arrayErrors = [];
|
|
1567
|
+
}
|
|
1568
|
+
/**
|
|
1569
|
+
* Gets the current values of all form groups in the array.
|
|
1570
|
+
*
|
|
1571
|
+
* @returns An array of cloned plain-object values from each FormGroup.
|
|
1572
|
+
*/
|
|
1573
|
+
get() {
|
|
1574
|
+
return this.groups.map(g => g.get());
|
|
1575
|
+
}
|
|
1576
|
+
/**
|
|
1577
|
+
* Gets the value of a specific form group in the array.
|
|
1578
|
+
*
|
|
1579
|
+
* @param index - The index of the group.
|
|
1580
|
+
* @returns A cloned copy of the group's value, or undefined if out of bounds.
|
|
1581
|
+
*/
|
|
1582
|
+
getAt(index) {
|
|
1583
|
+
if (index < 0 || index >= this.groups.length) {
|
|
1584
|
+
return undefined;
|
|
1585
|
+
}
|
|
1586
|
+
return this.groups[index].get();
|
|
1587
|
+
}
|
|
1588
|
+
/**
|
|
1589
|
+
* Gets the FormGroup instance at the specified index.
|
|
1590
|
+
*
|
|
1591
|
+
* @param index - The index of the group.
|
|
1592
|
+
* @returns The FormGroup instance, or undefined if out of bounds.
|
|
1593
|
+
*/
|
|
1594
|
+
getGroup(index) {
|
|
1595
|
+
if (index < 0 || index >= this.groups.length) {
|
|
1596
|
+
return undefined;
|
|
1597
|
+
}
|
|
1598
|
+
return this.groups[index];
|
|
1599
|
+
}
|
|
1600
|
+
/**
|
|
1601
|
+
* Returns a shallow copy of all FormGroup instances.
|
|
1602
|
+
*/
|
|
1603
|
+
getGroups() {
|
|
1604
|
+
return [...this.groups];
|
|
1605
|
+
}
|
|
1606
|
+
/**
|
|
1607
|
+
* Gets a property value from the FormGroup at the specified index.
|
|
1608
|
+
*
|
|
1609
|
+
* @param index - The index of the group.
|
|
1610
|
+
* @param key - The property key to retrieve.
|
|
1611
|
+
* @returns The property value, or undefined if not found.
|
|
1612
|
+
*/
|
|
1613
|
+
getProperty(index, key) {
|
|
1614
|
+
const group = this.getGroup(index);
|
|
1615
|
+
return group ? group.get(key) : undefined;
|
|
1616
|
+
}
|
|
1617
|
+
/**
|
|
1618
|
+
* Sets the values of all groups. Updates existing groups in-place and
|
|
1619
|
+
* discards any excess groups. Does not create new groups for excess values.
|
|
1620
|
+
*
|
|
1621
|
+
* @param values - The new values for the groups.
|
|
1622
|
+
*/
|
|
1623
|
+
set(values) {
|
|
1624
|
+
const len = Math.min(values.length, this.groups.length);
|
|
1625
|
+
for (let i = 0; i < len; i++) {
|
|
1626
|
+
const val = values[i];
|
|
1627
|
+
for (const key in val) {
|
|
1628
|
+
this.groups[i].set(key, val[key]);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
// If fewer values than groups, remove excess groups
|
|
1632
|
+
if (values.length < this.groups.length) {
|
|
1633
|
+
this.setGroups(old => old.slice(0, values.length));
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
/**
|
|
1637
|
+
* Sets the value of a group at the specified index.
|
|
1638
|
+
*
|
|
1639
|
+
* @param index - The index of the group to update.
|
|
1640
|
+
* @param value - The new value for the group.
|
|
1641
|
+
*/
|
|
1642
|
+
setAt(index, value) {
|
|
1643
|
+
const group = this.getGroup(index);
|
|
1644
|
+
if (!group) {
|
|
1645
|
+
console.error(`Index ${index} out of bounds.`);
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
for (const key in value) {
|
|
1649
|
+
group.set(key, value[key]);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
/**
|
|
1653
|
+
* Sets a property value on the FormGroup at the specified index.
|
|
1654
|
+
*
|
|
1655
|
+
* @param index - The index of the group.
|
|
1656
|
+
* @param key - The property key to set.
|
|
1657
|
+
* @param value - The new value for the property.
|
|
1658
|
+
*/
|
|
1659
|
+
setProperty(index, key, value) {
|
|
1660
|
+
const group = this.getGroup(index);
|
|
1661
|
+
if (!group) {
|
|
1662
|
+
console.error(`Index ${index} out of bounds.`);
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
group.set(key, value);
|
|
1666
|
+
}
|
|
1667
|
+
/**
|
|
1668
|
+
* Removes a group at the specified index.
|
|
1669
|
+
*
|
|
1670
|
+
* @param index - The index of the group to remove.
|
|
1671
|
+
*/
|
|
1672
|
+
remove(index) {
|
|
1673
|
+
this.setGroups(old => {
|
|
1674
|
+
const copy = [...old];
|
|
1675
|
+
copy.splice(index, 1);
|
|
1676
|
+
return copy;
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1679
|
+
/**
|
|
1680
|
+
* Replaces a group at the specified index with a new FormGroup.
|
|
1681
|
+
*
|
|
1682
|
+
* @param index - The index of the group to replace.
|
|
1683
|
+
* @param group - The new FormGroup instance.
|
|
1684
|
+
*/
|
|
1685
|
+
replace(index, group) {
|
|
1686
|
+
this.setGroups(old => {
|
|
1687
|
+
const copy = [...old];
|
|
1688
|
+
copy[index] = group;
|
|
1689
|
+
return copy;
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1692
|
+
/**
|
|
1693
|
+
* Adds a new FormGroup to the array.
|
|
1694
|
+
*
|
|
1695
|
+
* @param group - The FormGroup instance to add.
|
|
1696
|
+
*/
|
|
1697
|
+
add(group) {
|
|
1698
|
+
this.setGroups(old => [...old, group]);
|
|
1699
|
+
}
|
|
1700
|
+
/**
|
|
1701
|
+
* Checks if any validation errors exist.
|
|
1702
|
+
*
|
|
1703
|
+
* @param index - (Optional) The index of the group to check for errors.
|
|
1704
|
+
* If not provided, checks all groups and array-level errors.
|
|
1705
|
+
* @returns `true` if any errors are found, otherwise `false`.
|
|
1706
|
+
*/
|
|
1707
|
+
hasError(index) {
|
|
1708
|
+
if (index !== undefined && index !== null) {
|
|
1709
|
+
const group = this.getGroup(index);
|
|
1710
|
+
if (!group) return false;
|
|
1711
|
+
return group.hasAnyError();
|
|
1712
|
+
}
|
|
1713
|
+
const anyGroupError = this.groups.some(g => g.hasAnyError());
|
|
1714
|
+
const anyArrayError = this.arrayErrors.some(e => e.hasError);
|
|
1715
|
+
return anyGroupError || anyArrayError;
|
|
1716
|
+
}
|
|
1717
|
+
/**
|
|
1718
|
+
* Checks if a specific validator error exists for a group at the given index.
|
|
1719
|
+
*
|
|
1720
|
+
* @param index - The index of the group.
|
|
1721
|
+
* @param errKey - The key identifying the specific error to check for.
|
|
1722
|
+
* @returns `true` if the specific error is present, otherwise `false`.
|
|
1723
|
+
*/
|
|
1724
|
+
hasValidator(index, errKey) {
|
|
1725
|
+
const group = this.getGroup(index);
|
|
1726
|
+
if (!group) return false;
|
|
1727
|
+
return group.hasAnyValidator(errKey);
|
|
1728
|
+
}
|
|
1729
|
+
/**
|
|
1730
|
+
* Gets all errors for the form array.
|
|
1731
|
+
* Each inner array contains the errors from one FormGroup plus array-level errors.
|
|
1732
|
+
*
|
|
1733
|
+
* @returns An array of error arrays for each group.
|
|
1734
|
+
*/
|
|
1735
|
+
getErrors() {
|
|
1736
|
+
return this.groups.map(g => {
|
|
1737
|
+
return [...g.getAllErrors(), ...Clone(this.arrayErrors)];
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Gets errors for a specific group in the array.
|
|
1742
|
+
*
|
|
1743
|
+
* @param index - The index of the group.
|
|
1744
|
+
* @returns An array of errors for the group, or an empty array if not found.
|
|
1745
|
+
*/
|
|
1746
|
+
getErrorsAt(index) {
|
|
1747
|
+
const group = this.getGroup(index);
|
|
1748
|
+
if (!group) return [];
|
|
1749
|
+
return [...group.getAllErrors(), ...Clone(this.arrayErrors)];
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1752
|
+
* Gets only array-level errors (not per-group errors).
|
|
1753
|
+
*/
|
|
1754
|
+
getArrayErrors() {
|
|
1755
|
+
return Clone(this.arrayErrors);
|
|
1756
|
+
}
|
|
1757
|
+
/**
|
|
1758
|
+
* Validates the form array using current values.
|
|
1759
|
+
*
|
|
1760
|
+
* @param index - Optional index to validate just one group.
|
|
1761
|
+
* @returns True if validation passes, false otherwise.
|
|
1762
|
+
*/
|
|
1763
|
+
validateCurrent(index) {
|
|
1764
|
+
return this.validate(index);
|
|
1765
|
+
}
|
|
1766
|
+
/**
|
|
1767
|
+
* Validates the form array.
|
|
1768
|
+
*
|
|
1769
|
+
* @param index - (Optional) The index of a single group to validate.
|
|
1770
|
+
* If not provided, validates all groups and array-level validators.
|
|
1771
|
+
* @returns `true` if all validations pass, otherwise `false`.
|
|
1772
|
+
*/
|
|
1773
|
+
validate(index) {
|
|
1774
|
+
// Run array-level validators
|
|
1775
|
+
const values = this.get();
|
|
1776
|
+
this.arrayErrors = this.internalArrayValidation.map(validator => ({
|
|
1777
|
+
key: validator.errKey,
|
|
1778
|
+
hasError: !validator.revalidate(values)
|
|
1779
|
+
}));
|
|
1780
|
+
const arrayValid = this.arrayErrors.every(e => !e.hasError);
|
|
1781
|
+
if (index !== undefined && index !== null) {
|
|
1782
|
+
const group = this.getGroup(index);
|
|
1783
|
+
if (!group) return false;
|
|
1784
|
+
const groupValid = group.validate();
|
|
1785
|
+
return groupValid && arrayValid;
|
|
1786
|
+
}
|
|
1787
|
+
// Validate all groups
|
|
1788
|
+
const groupResults = this.groups.map(g => g.validate());
|
|
1789
|
+
const allGroupsValid = groupResults.every(Boolean);
|
|
1790
|
+
return allGroupsValid && arrayValid;
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1496
1794
|
var _tmpl$$j = /*#__PURE__*/template(`<form>`);
|
|
1497
1795
|
const FormContext = createContext();
|
|
1498
1796
|
const useFormContext = () => {
|
|
1499
1797
|
return useContext(FormContext);
|
|
1500
1798
|
};
|
|
1501
1799
|
const Form = props => {
|
|
1502
|
-
|
|
1800
|
+
if (props.data instanceof FormArray) {
|
|
1801
|
+
const fa = props.data;
|
|
1802
|
+
return createComponent(ArrayProvider, {
|
|
1803
|
+
formArray: fa,
|
|
1804
|
+
get children() {
|
|
1805
|
+
return createComponent(FormInnerArray, {
|
|
1806
|
+
get onSubmit() {
|
|
1807
|
+
return props.onSubmit;
|
|
1808
|
+
},
|
|
1809
|
+
get children() {
|
|
1810
|
+
return props.children;
|
|
1811
|
+
},
|
|
1812
|
+
formArray: fa
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
const fg = props.data;
|
|
1818
|
+
const startData = fg.get() ?? {};
|
|
1503
1819
|
// Custom shallow clone preserving FormArray instances (already handled in FormGroup.get)
|
|
1504
1820
|
const initialValue = {};
|
|
1505
1821
|
Object.keys(startData).forEach(k => {
|
|
@@ -1507,11 +1823,17 @@ const Form = props => {
|
|
|
1507
1823
|
});
|
|
1508
1824
|
return createComponent(Provider, {
|
|
1509
1825
|
value: initialValue,
|
|
1510
|
-
|
|
1511
|
-
return props.data;
|
|
1512
|
-
},
|
|
1826
|
+
formGroup: fg,
|
|
1513
1827
|
get children() {
|
|
1514
|
-
return createComponent(FormInner,
|
|
1828
|
+
return createComponent(FormInner, {
|
|
1829
|
+
data: fg,
|
|
1830
|
+
get onSubmit() {
|
|
1831
|
+
return props.onSubmit;
|
|
1832
|
+
},
|
|
1833
|
+
get children() {
|
|
1834
|
+
return props.children;
|
|
1835
|
+
}
|
|
1836
|
+
});
|
|
1515
1837
|
}
|
|
1516
1838
|
});
|
|
1517
1839
|
};
|
|
@@ -1521,7 +1843,7 @@ const FormInner = props => {
|
|
|
1521
1843
|
const submitFunction = e => {
|
|
1522
1844
|
const submitData = CloneStore(formData?.data ?? {});
|
|
1523
1845
|
e.preventDefault();
|
|
1524
|
-
if (formData.formGroup
|
|
1846
|
+
if (formData.formGroup?.validate()) {
|
|
1525
1847
|
props?.onSubmit?.(submitData);
|
|
1526
1848
|
}
|
|
1527
1849
|
};
|
|
@@ -1538,6 +1860,27 @@ const FormInner = props => {
|
|
|
1538
1860
|
return _el$;
|
|
1539
1861
|
})();
|
|
1540
1862
|
};
|
|
1863
|
+
const FormInnerArray = props => {
|
|
1864
|
+
const [formRef, setFormRef] = createSignal();
|
|
1865
|
+
const submitFunction = e => {
|
|
1866
|
+
e.preventDefault();
|
|
1867
|
+
if (props.formArray.validateCurrent()) {
|
|
1868
|
+
props.onSubmit(props.formArray.get());
|
|
1869
|
+
}
|
|
1870
|
+
};
|
|
1871
|
+
createEffect(() => {
|
|
1872
|
+
formRef()?.addEventListener('submit', submitFunction);
|
|
1873
|
+
});
|
|
1874
|
+
onCleanup(() => {
|
|
1875
|
+
formRef()?.removeEventListener('submit', submitFunction);
|
|
1876
|
+
});
|
|
1877
|
+
return (() => {
|
|
1878
|
+
var _el$2 = _tmpl$$j();
|
|
1879
|
+
use(setFormRef, _el$2);
|
|
1880
|
+
insert(_el$2, () => props.children);
|
|
1881
|
+
return _el$2;
|
|
1882
|
+
})();
|
|
1883
|
+
};
|
|
1541
1884
|
const Provider = props => {
|
|
1542
1885
|
const defaultData = props.value ?? {};
|
|
1543
1886
|
const [data, setData] = createStore(defaultData);
|
|
@@ -1565,19 +1908,136 @@ const Provider = props => {
|
|
|
1565
1908
|
}
|
|
1566
1909
|
});
|
|
1567
1910
|
};
|
|
1911
|
+
const ArrayProvider = props => {
|
|
1912
|
+
const [data, setData] = createStore({});
|
|
1913
|
+
return createComponent(FormContext.Provider, {
|
|
1914
|
+
get value() {
|
|
1915
|
+
return {
|
|
1916
|
+
data,
|
|
1917
|
+
setData,
|
|
1918
|
+
formArray: props.formArray
|
|
1919
|
+
};
|
|
1920
|
+
},
|
|
1921
|
+
get children() {
|
|
1922
|
+
return props.children;
|
|
1923
|
+
}
|
|
1924
|
+
});
|
|
1925
|
+
};
|
|
1926
|
+
|
|
1927
|
+
/**
|
|
1928
|
+
* Hook that resolves form binding from direct props, with FormField context as fallback.
|
|
1929
|
+
*
|
|
1930
|
+
* Supports three binding modes:
|
|
1931
|
+
* 1. **FormGroup (simple)**: `formName` binds to `formGroup.data[formName]`
|
|
1932
|
+
* 2. **FormArray (top-level)**: `formIndex` + `formName` binds to `formArray.getAt(formIndex)[formName]`
|
|
1933
|
+
* 3. **FormArray (within FormGroup)**: `formArrayName` + `formIndex` + `formName` binds to
|
|
1934
|
+
* `formGroup.data[formArrayName].getAt(formIndex)[formName]`
|
|
1935
|
+
*
|
|
1936
|
+
* Priority: direct props > FormField context > undefined
|
|
1937
|
+
*/
|
|
1938
|
+
function useDirectFormBinding(props) {
|
|
1939
|
+
const fieldContext = useFormProvider();
|
|
1940
|
+
const formContext = useFormContext();
|
|
1941
|
+
const resolvedFormName = props.formName ?? fieldContext?.formName;
|
|
1942
|
+
// Determine which FormArray we're targeting (if any)
|
|
1943
|
+
const resolvedFormArray = createMemo(() => {
|
|
1944
|
+
if (props.formIndex === undefined) return undefined;
|
|
1945
|
+
// Top-level FormArray
|
|
1946
|
+
if (formContext?.formArray) {
|
|
1947
|
+
return formContext.formArray;
|
|
1948
|
+
}
|
|
1949
|
+
// FormArray within FormGroup
|
|
1950
|
+
if (props.formArrayName && formContext?.formGroup) {
|
|
1951
|
+
const field = formContext.formGroup.getR(props.formArrayName);
|
|
1952
|
+
if (field instanceof FormArray) {
|
|
1953
|
+
return field;
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
return undefined;
|
|
1957
|
+
});
|
|
1958
|
+
const isFormArray = createMemo(() => !!resolvedFormArray());
|
|
1959
|
+
const getValue = () => {
|
|
1960
|
+
const fa = resolvedFormArray();
|
|
1961
|
+
if (fa && props.formIndex !== undefined && resolvedFormName) {
|
|
1962
|
+
return fa.getProperty(props.formIndex, resolvedFormName);
|
|
1963
|
+
}
|
|
1964
|
+
// Simple FormGroup binding
|
|
1965
|
+
if (resolvedFormName && formContext?.data) {
|
|
1966
|
+
return formContext.data[resolvedFormName];
|
|
1967
|
+
}
|
|
1968
|
+
return undefined;
|
|
1969
|
+
};
|
|
1970
|
+
const setValue = val => {
|
|
1971
|
+
const fa = resolvedFormArray();
|
|
1972
|
+
if (fa && props.formIndex !== undefined && resolvedFormName) {
|
|
1973
|
+
fa.setProperty(props.formIndex, resolvedFormName, val);
|
|
1974
|
+
return;
|
|
1975
|
+
}
|
|
1976
|
+
// Simple FormGroup binding
|
|
1977
|
+
if (resolvedFormName && formContext?.formGroup) {
|
|
1978
|
+
formContext.formGroup.set(resolvedFormName, val);
|
|
1979
|
+
formContext.setData?.(resolvedFormName, val);
|
|
1980
|
+
}
|
|
1981
|
+
};
|
|
1982
|
+
const markDirty = () => {
|
|
1983
|
+
const fa = resolvedFormArray();
|
|
1984
|
+
if (fa && props.formIndex !== undefined && resolvedFormName) {
|
|
1985
|
+
const group = fa.getGroup(props.formIndex);
|
|
1986
|
+
if (group) {
|
|
1987
|
+
group.markDirty(resolvedFormName);
|
|
1988
|
+
}
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
if (resolvedFormName && formContext?.formGroup) {
|
|
1992
|
+
const meta = formContext.formGroup.getMeta(resolvedFormName);
|
|
1993
|
+
if (meta && !meta.dirty) {
|
|
1994
|
+
formContext.formGroup.markDirty(resolvedFormName);
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
};
|
|
1998
|
+
const validate = () => {
|
|
1999
|
+
const fa = resolvedFormArray();
|
|
2000
|
+
if (fa && props.formIndex !== undefined) {
|
|
2001
|
+
return fa.validateCurrent(props.formIndex);
|
|
2002
|
+
}
|
|
2003
|
+
if (resolvedFormName && formContext?.formGroup) {
|
|
2004
|
+
return formContext.formGroup.validate(resolvedFormName);
|
|
2005
|
+
}
|
|
2006
|
+
return undefined;
|
|
2007
|
+
};
|
|
2008
|
+
return {
|
|
2009
|
+
formName: resolvedFormName,
|
|
2010
|
+
getValue,
|
|
2011
|
+
setValue,
|
|
2012
|
+
markDirty,
|
|
2013
|
+
validate,
|
|
2014
|
+
formGroup: formContext?.formGroup,
|
|
2015
|
+
formArray: resolvedFormArray(),
|
|
2016
|
+
isFormArray: isFormArray()
|
|
2017
|
+
};
|
|
2018
|
+
}
|
|
1568
2019
|
|
|
1569
2020
|
var _tmpl$$i = /*#__PURE__*/template(`<input>`);
|
|
1570
2021
|
const Input = props => {
|
|
1571
|
-
const [customProps, normalProps] = splitProps(props, ["tooltip", "transparent", "value", "onChange"]);
|
|
2022
|
+
const [customProps, normalProps] = splitProps(props, ["tooltip", "transparent", "value", "onChange", "formName", "formIndex", "formArrayName"]);
|
|
1572
2023
|
const context = useFormProvider();
|
|
1573
2024
|
const formContext = useFormContext();
|
|
2025
|
+
const binding = useDirectFormBinding({
|
|
2026
|
+
formName: props.formName,
|
|
2027
|
+
formIndex: props.formIndex,
|
|
2028
|
+
formArrayName: props.formArrayName
|
|
2029
|
+
});
|
|
2030
|
+
const effectiveFormName = binding.formName;
|
|
1574
2031
|
// Determine the input's value using form context or provided prop value
|
|
1575
2032
|
const inputValue = createMemo(() => {
|
|
1576
2033
|
if (!isNullish(props?.value)) {
|
|
1577
2034
|
return props.value;
|
|
1578
2035
|
}
|
|
1579
|
-
if (
|
|
1580
|
-
return
|
|
2036
|
+
if (binding.isFormArray) {
|
|
2037
|
+
return binding.getValue();
|
|
2038
|
+
}
|
|
2039
|
+
if (!isNullish(formContext?.data?.[effectiveFormName ?? ""])) {
|
|
2040
|
+
return formContext.data[effectiveFormName ?? ""];
|
|
1581
2041
|
}
|
|
1582
2042
|
if (!isNullish(context.getValue)) {
|
|
1583
2043
|
return context.getValue();
|
|
@@ -1586,20 +2046,23 @@ const Input = props => {
|
|
|
1586
2046
|
});
|
|
1587
2047
|
const isRequired = createMemo(() => {
|
|
1588
2048
|
if (context && formContext) {
|
|
1589
|
-
const key =
|
|
2049
|
+
const key = effectiveFormName ?? "";
|
|
1590
2050
|
return formContext?.formGroup?.hasValidator?.(key, 'required');
|
|
1591
2051
|
}
|
|
1592
2052
|
return Object.keys(normalProps).includes("required") && props?.required !== false || props?.required === true;
|
|
1593
2053
|
});
|
|
1594
2054
|
// onChange only handles non-checkbox values
|
|
1595
2055
|
const onChange = e => {
|
|
1596
|
-
if (
|
|
2056
|
+
if (binding.isFormArray) {
|
|
2057
|
+
binding.setValue(e.currentTarget.value);
|
|
2058
|
+
context?.setTextInside?.(!isNullish(e.currentTarget.value) && e.currentTarget.value?.trim() !== "");
|
|
2059
|
+
} else if (!isNullish(formContext?.setData) && !!formContext?.formGroup?.get) {
|
|
1597
2060
|
const textInside = !isNullish(e.currentTarget.value) && e.currentTarget.value?.trim() !== "";
|
|
1598
2061
|
context?.setTextInside?.(textInside);
|
|
1599
|
-
formContext.formGroup?.set?.(
|
|
2062
|
+
formContext.formGroup?.set?.(effectiveFormName ?? "", e.currentTarget.value);
|
|
1600
2063
|
formContext?.setData?.(old => ({
|
|
1601
2064
|
...old,
|
|
1602
|
-
[
|
|
2065
|
+
[effectiveFormName ?? ""]: e.currentTarget.value
|
|
1603
2066
|
}));
|
|
1604
2067
|
} else if (!isNullish(context.getName) && !!context?.getName?.()) {
|
|
1605
2068
|
if (e.currentTarget.value.trim()) {
|
|
@@ -1618,7 +2081,7 @@ const Input = props => {
|
|
|
1618
2081
|
// Force a non-checkbox field type
|
|
1619
2082
|
context.setFieldType(props.type === "checkbox" ? "text" : props.type ?? "text");
|
|
1620
2083
|
if (!isNullish(formContext?.data)) {
|
|
1621
|
-
const raw = formContext.data[
|
|
2084
|
+
const raw = formContext.data[effectiveFormName ?? ""];
|
|
1622
2085
|
if (typeof raw === 'string') {
|
|
1623
2086
|
const formValue = raw.trim();
|
|
1624
2087
|
if (formValue) {
|
|
@@ -1680,6 +2143,10 @@ const Input = props => {
|
|
|
1680
2143
|
if (props.disabled) return;
|
|
1681
2144
|
if (!isNullish(context.getName)) {
|
|
1682
2145
|
context.setFocused?.(true);
|
|
2146
|
+
if (effectiveFormName && formContext?.formGroup?.markDirty) {
|
|
2147
|
+
const meta = formContext.formGroup.getMeta(effectiveFormName);
|
|
2148
|
+
if (meta && !meta.dirty) formContext.formGroup.markDirty(effectiveFormName);
|
|
2149
|
+
}
|
|
1683
2150
|
}
|
|
1684
2151
|
},
|
|
1685
2152
|
"onBlur": e => {
|
|
@@ -1687,12 +2154,12 @@ const Input = props => {
|
|
|
1687
2154
|
if (!isNullish(context.getName)) {
|
|
1688
2155
|
context?.setFocused?.(prev => {
|
|
1689
2156
|
if (prev) {
|
|
1690
|
-
formContext?.formGroup?.validate?.(
|
|
2157
|
+
formContext?.formGroup?.validate?.(effectiveFormName ?? "");
|
|
1691
2158
|
}
|
|
1692
2159
|
return false;
|
|
1693
2160
|
});
|
|
1694
2161
|
const noValue = !e.currentTarget?.value?.trim();
|
|
1695
|
-
const noFormValue = !formContext?.data?.[
|
|
2162
|
+
const noFormValue = !formContext?.data?.[effectiveFormName ?? ""];
|
|
1696
2163
|
const noContextValue = !context?.getValue();
|
|
1697
2164
|
context.setTextInside(noValue && noFormValue && noContextValue);
|
|
1698
2165
|
}
|
|
@@ -1721,12 +2188,18 @@ var _tmpl$$h = /*#__PURE__*/template(`<label><input type=checkbox><span>`),
|
|
|
1721
2188
|
function Checkbox(props) {
|
|
1722
2189
|
const field = useFormProvider();
|
|
1723
2190
|
const formCtx = useFormContext();
|
|
1724
|
-
const
|
|
2191
|
+
const binding = useDirectFormBinding({
|
|
2192
|
+
formName: props.formName,
|
|
2193
|
+
formIndex: props.formIndex,
|
|
2194
|
+
formArrayName: props.formArrayName
|
|
2195
|
+
});
|
|
2196
|
+
const formName = binding.formName;
|
|
1725
2197
|
// Internal state for uncontrolled usage outside form context
|
|
1726
2198
|
const [internalChecked, setInternalChecked] = createSignal(props.defaultChecked ?? false);
|
|
1727
|
-
// Derive current checked state with priority: controlled prop -> form context -> field local value -> internal state
|
|
2199
|
+
// Derive current checked state with priority: controlled prop -> FormArray -> form context -> field local value -> internal state
|
|
1728
2200
|
const checkedState = createMemo(() => {
|
|
1729
2201
|
if (props.checked !== undefined) return !!props.checked;
|
|
2202
|
+
if (binding.isFormArray) return !!binding.getValue();
|
|
1730
2203
|
if (formName && formCtx?.data) return !!formCtx.data[formName];
|
|
1731
2204
|
if (field?.getValue) return !!field.getValue();
|
|
1732
2205
|
return internalChecked();
|
|
@@ -1741,7 +2214,9 @@ function Checkbox(props) {
|
|
|
1741
2214
|
});
|
|
1742
2215
|
const commitValue = next => {
|
|
1743
2216
|
if (props.checked === undefined) {
|
|
1744
|
-
if (
|
|
2217
|
+
if (binding.isFormArray) {
|
|
2218
|
+
binding.setValue(next);
|
|
2219
|
+
} else if (formName && formCtx?.formGroup) {
|
|
1745
2220
|
formCtx.formGroup.set(formName, next);
|
|
1746
2221
|
formCtx.setData?.(formName, next);
|
|
1747
2222
|
} else if (field?.setValue) {
|
|
@@ -1856,6 +2331,9 @@ function getEntryAmount() {
|
|
|
1856
2331
|
function ignoreWindowManager(element) {
|
|
1857
2332
|
manager.ignoreElement(element);
|
|
1858
2333
|
}
|
|
2334
|
+
function unignoreWindowManager(element) {
|
|
2335
|
+
manager.unignoreElement(element);
|
|
2336
|
+
}
|
|
1859
2337
|
// Unregister the given element.
|
|
1860
2338
|
function unregisterWindowManager(entry) {
|
|
1861
2339
|
manager.unregister(entry);
|
|
@@ -2081,6 +2559,7 @@ function Select(props) {
|
|
|
2081
2559
|
const [selectRef, setSelectRef] = createSignal();
|
|
2082
2560
|
const [dropdownRef, setDropdownRef] = createSignal();
|
|
2083
2561
|
const [mobilePopupRef, setMobilePopupRef] = createSignal();
|
|
2562
|
+
let mobileOptionsRef;
|
|
2084
2563
|
// Resolved rendering mode: 'popup' for fullscreen mobile popup, 'desktop' for traditional dropdown
|
|
2085
2564
|
const resolvedMode = createMemo(() => {
|
|
2086
2565
|
const mode = props.mobileMode ?? 'auto';
|
|
@@ -2091,11 +2570,17 @@ function Select(props) {
|
|
|
2091
2570
|
});
|
|
2092
2571
|
const form = useFormProvider();
|
|
2093
2572
|
const formContext = useFormContext();
|
|
2094
|
-
const
|
|
2573
|
+
const binding = useDirectFormBinding({
|
|
2574
|
+
formName: props.formName,
|
|
2575
|
+
formIndex: props.formIndex,
|
|
2576
|
+
formArrayName: props.formArrayName
|
|
2577
|
+
});
|
|
2578
|
+
const effectiveFormName = binding.formName;
|
|
2579
|
+
const hasForm = !!effectiveFormName || !!effectiveFormName || !!form?.getName || !!form?.getValue || !!form?.setValue || !!form?.getTextInside;
|
|
2095
2580
|
const hasFormContext = hasForm && !!formContext?.formGroup;
|
|
2096
2581
|
const currentValue = () => {
|
|
2097
2582
|
if (hasFormContext) {
|
|
2098
|
-
return formContext.data?.[
|
|
2583
|
+
return formContext.data?.[effectiveFormName ?? ''];
|
|
2099
2584
|
}
|
|
2100
2585
|
if (hasForm) {
|
|
2101
2586
|
return form.getValue();
|
|
@@ -2163,9 +2648,9 @@ function Select(props) {
|
|
|
2163
2648
|
// Function to handle selecting/toggling an option for single or multi-select
|
|
2164
2649
|
// When not using a form or greater FormContext
|
|
2165
2650
|
const selectValue = val => {
|
|
2166
|
-
if (
|
|
2167
|
-
const meta = formContext.formGroup.getMeta(
|
|
2168
|
-
if (meta && !meta.dirty) formContext.formGroup.markDirty(
|
|
2651
|
+
if (effectiveFormName && formContext?.formGroup?.markDirty) {
|
|
2652
|
+
const meta = formContext.formGroup.getMeta(effectiveFormName);
|
|
2653
|
+
if (meta && !meta.dirty) formContext.formGroup.markDirty(effectiveFormName);
|
|
2169
2654
|
}
|
|
2170
2655
|
if (isMultiple) {
|
|
2171
2656
|
// For multi-select, toggle the value in the array
|
|
@@ -2176,9 +2661,16 @@ function Select(props) {
|
|
|
2176
2661
|
} else {
|
|
2177
2662
|
newSelected = [...current, val];
|
|
2178
2663
|
}
|
|
2664
|
+
// Preserve scroll position in mobile popup before reactive updates
|
|
2665
|
+
const savedScrollTop = mobileOptionsRef?.scrollTop;
|
|
2179
2666
|
setSelected(() => newSelected);
|
|
2180
2667
|
props?.onChange?.(newSelected);
|
|
2181
2668
|
props?.onSelect?.(newSelected);
|
|
2669
|
+
if (savedScrollTop != null && mobileOptionsRef) {
|
|
2670
|
+
queueMicrotask(() => {
|
|
2671
|
+
mobileOptionsRef.scrollTop = savedScrollTop;
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2182
2674
|
} else {
|
|
2183
2675
|
setSelected(() => val);
|
|
2184
2676
|
props?.onChange?.(val);
|
|
@@ -2287,7 +2779,7 @@ function Select(props) {
|
|
|
2287
2779
|
setOpen(false);
|
|
2288
2780
|
form?.setFocused?.(prev => {
|
|
2289
2781
|
if (prev) {
|
|
2290
|
-
formContext?.formGroup?.validate?.(
|
|
2782
|
+
formContext?.formGroup?.validate?.(effectiveFormName ?? '');
|
|
2291
2783
|
}
|
|
2292
2784
|
return false;
|
|
2293
2785
|
});
|
|
@@ -2329,7 +2821,7 @@ function Select(props) {
|
|
|
2329
2821
|
setOpen(false);
|
|
2330
2822
|
form?.setFocused?.(prev => {
|
|
2331
2823
|
if (prev) {
|
|
2332
|
-
formContext?.formGroup?.validate?.(
|
|
2824
|
+
formContext?.formGroup?.validate?.(effectiveFormName ?? '');
|
|
2333
2825
|
}
|
|
2334
2826
|
return false;
|
|
2335
2827
|
});
|
|
@@ -2406,7 +2898,8 @@ function Select(props) {
|
|
|
2406
2898
|
isDisabled,
|
|
2407
2899
|
closeDropdown: () => {
|
|
2408
2900
|
if (!isMultiple) setOpen(false);
|
|
2409
|
-
}
|
|
2901
|
+
},
|
|
2902
|
+
formName: effectiveFormName
|
|
2410
2903
|
}));
|
|
2411
2904
|
// --- Keyboard handler ---
|
|
2412
2905
|
const handleKeyDown = e => {
|
|
@@ -2513,6 +3006,10 @@ function Select(props) {
|
|
|
2513
3006
|
_el$7.addEventListener("focus", () => {
|
|
2514
3007
|
if (isDisabled()) return;
|
|
2515
3008
|
form?.setFocused?.(true);
|
|
3009
|
+
if (effectiveFormName && formContext?.formGroup?.markDirty) {
|
|
3010
|
+
const meta = formContext.formGroup.getMeta(effectiveFormName);
|
|
3011
|
+
if (meta && !meta.dirty) formContext.formGroup.markDirty(effectiveFormName);
|
|
3012
|
+
}
|
|
2516
3013
|
});
|
|
2517
3014
|
_el$7._$owner = getOwner();
|
|
2518
3015
|
_el$8.$$click = e => {
|
|
@@ -2608,6 +3105,8 @@ function Select(props) {
|
|
|
2608
3105
|
use(setMobilePopupRef, _el$14);
|
|
2609
3106
|
insert(_el$16, mobilePopupTitle);
|
|
2610
3107
|
_el$17.$$click = () => closeMobilePopup();
|
|
3108
|
+
var _ref$ = mobileOptionsRef;
|
|
3109
|
+
typeof _ref$ === "function" ? use(_ref$, _el$18) : mobileOptionsRef = _el$18;
|
|
2611
3110
|
insert(_el$18, () => props.children);
|
|
2612
3111
|
insert(_el$14, createComponent(Show, {
|
|
2613
3112
|
when: isMultiple,
|
|
@@ -2735,30 +3234,30 @@ function Option(props) {
|
|
|
2735
3234
|
};
|
|
2736
3235
|
const selectFormContextValue = value => {
|
|
2737
3236
|
if (formContext) {
|
|
2738
|
-
const currentValue = formContext.data[formField?.formName ?? ''];
|
|
3237
|
+
const currentValue = formContext.data[select?.formName ?? formField?.formName ?? ''];
|
|
2739
3238
|
formField?.setFocused?.(true);
|
|
2740
3239
|
if (Array.isArray(currentValue)) {
|
|
2741
3240
|
if (currentValue.includes(value)) {
|
|
2742
3241
|
const setValue = currentValue.filter(val => val !== value);
|
|
2743
|
-
formContext
|
|
3242
|
+
formContext?.formGroup?.set?.(select?.formName ?? formField?.formName ?? '', setValue);
|
|
2744
3243
|
formContext.setData(old => ({
|
|
2745
3244
|
...old,
|
|
2746
|
-
[formField?.formName ?? '']: setValue
|
|
3245
|
+
[select?.formName ?? formField?.formName ?? '']: setValue
|
|
2747
3246
|
}));
|
|
2748
3247
|
return true;
|
|
2749
3248
|
} else {
|
|
2750
|
-
formContext
|
|
3249
|
+
formContext?.formGroup?.set?.(select?.formName ?? formField?.formName ?? '', [...currentValue, value]);
|
|
2751
3250
|
formContext.setData(old => ({
|
|
2752
3251
|
...old,
|
|
2753
|
-
[formField?.formName ?? '']: [...currentValue, value]
|
|
3252
|
+
[select?.formName ?? formField?.formName ?? '']: [...currentValue, value]
|
|
2754
3253
|
}));
|
|
2755
3254
|
return true;
|
|
2756
3255
|
}
|
|
2757
3256
|
} else {
|
|
2758
|
-
formContext
|
|
3257
|
+
formContext?.formGroup?.set?.(select?.formName ?? formField?.formName ?? '', value);
|
|
2759
3258
|
formContext.setData(old => ({
|
|
2760
3259
|
...old,
|
|
2761
|
-
[formField?.formName ?? '']: value
|
|
3260
|
+
[select?.formName ?? formField?.formName ?? '']: value
|
|
2762
3261
|
}));
|
|
2763
3262
|
return true;
|
|
2764
3263
|
}
|
|
@@ -2770,7 +3269,7 @@ function Option(props) {
|
|
|
2770
3269
|
e.stopPropagation();
|
|
2771
3270
|
const contextSuccess = selectFormContextValue(props.value);
|
|
2772
3271
|
!contextSuccess ? selectFormFieldValue(props.value) : true;
|
|
2773
|
-
if (!formField?.getName?.()) {
|
|
3272
|
+
if (!formField?.getName?.() && !select?.formName) {
|
|
2774
3273
|
select.selectValue?.(props.value);
|
|
2775
3274
|
} else {
|
|
2776
3275
|
// Form handled the value — still need to close for single select
|
|
@@ -2825,14 +3324,23 @@ styleInject(css_248z$b);
|
|
|
2825
3324
|
var _tmpl$$e = /*#__PURE__*/template(`<textarea>`);
|
|
2826
3325
|
const TextArea = props => {
|
|
2827
3326
|
let myElement;
|
|
2828
|
-
const [customProps, normalProps] = splitProps(props, ["minSize", "text", "setText", "class", "tooltip", "transparent"]);
|
|
3327
|
+
const [customProps, normalProps] = splitProps(props, ["minSize", "text", "setText", "class", "tooltip", "transparent", "formName", "formIndex", "formArrayName"]);
|
|
2829
3328
|
const fieldCtx = useFormProvider();
|
|
2830
3329
|
const formCtx = useFormContext();
|
|
2831
|
-
const
|
|
3330
|
+
const binding = useDirectFormBinding({
|
|
3331
|
+
formName: props.formName,
|
|
3332
|
+
formIndex: props.formIndex,
|
|
3333
|
+
formArrayName: props.formArrayName
|
|
3334
|
+
});
|
|
3335
|
+
const formName = binding.formName;
|
|
2832
3336
|
// Internal state only used when not provided externally and not in form context.
|
|
2833
3337
|
const [internal, setInternal] = createSignal(customProps.text ? customProps.text() : "");
|
|
2834
|
-
// Determine current value priority: FormGroup -> external accessor -> internal state
|
|
3338
|
+
// Determine current value priority: FormArray -> FormGroup -> external accessor -> internal state
|
|
2835
3339
|
const areaValue = createMemo(() => {
|
|
3340
|
+
if (binding.isFormArray) {
|
|
3341
|
+
const val = binding.getValue();
|
|
3342
|
+
return val !== undefined && val !== null ? String(val) : '';
|
|
3343
|
+
}
|
|
2836
3344
|
if (formName && formCtx?.data && !isNullish(formCtx.data[formName])) {
|
|
2837
3345
|
return formCtx.data[formName];
|
|
2838
3346
|
}
|
|
@@ -2886,7 +3394,9 @@ const TextArea = props => {
|
|
|
2886
3394
|
if (props.disabled) return;
|
|
2887
3395
|
const newVal = e.currentTarget.value;
|
|
2888
3396
|
// Update whichever source is active
|
|
2889
|
-
if (
|
|
3397
|
+
if (binding.isFormArray) {
|
|
3398
|
+
binding.setValue(newVal);
|
|
3399
|
+
} else if (formName && formCtx?.formGroup) {
|
|
2890
3400
|
formCtx.formGroup.set(formName, newVal);
|
|
2891
3401
|
formCtx.setData?.(formName, newVal);
|
|
2892
3402
|
} else if (customProps.setText) {
|
|
@@ -3593,19 +4103,27 @@ function RadioGroup(props) {
|
|
|
3593
4103
|
radioGroupCount++;
|
|
3594
4104
|
const groupName = props.name ?? `radio-group-${radioGroupCount}`;
|
|
3595
4105
|
const [internalValue, setInternalValue] = createSignal(props.defaultValue);
|
|
3596
|
-
|
|
4106
|
+
useFormProvider();
|
|
3597
4107
|
const formContext = useFormContext();
|
|
4108
|
+
const binding = useDirectFormBinding({
|
|
4109
|
+
formName: props.formName,
|
|
4110
|
+
formIndex: props.formIndex,
|
|
4111
|
+
formArrayName: props.formArrayName
|
|
4112
|
+
});
|
|
4113
|
+
const effectiveFormName = binding.formName;
|
|
3598
4114
|
const selectedValue = () => props.value !== undefined ? props.value : internalValue();
|
|
3599
4115
|
const setSelectedValue = val => {
|
|
3600
4116
|
if (props.value === undefined) {
|
|
3601
4117
|
setInternalValue(val);
|
|
3602
4118
|
}
|
|
3603
|
-
// Bridge to FormGroup
|
|
3604
|
-
if (
|
|
3605
|
-
|
|
4119
|
+
// Bridge to FormGroup/FormArray
|
|
4120
|
+
if (binding.isFormArray && effectiveFormName) {
|
|
4121
|
+
binding.setValue(val);
|
|
4122
|
+
} else if (effectiveFormName && formContext?.formGroup?.set) {
|
|
4123
|
+
formContext.formGroup.set(effectiveFormName, val);
|
|
3606
4124
|
formContext.setData(old => ({
|
|
3607
4125
|
...old,
|
|
3608
|
-
[
|
|
4126
|
+
[effectiveFormName]: val
|
|
3609
4127
|
}));
|
|
3610
4128
|
}
|
|
3611
4129
|
props.onChange?.(val);
|
|
@@ -3798,334 +4316,6 @@ function Radio(props) {
|
|
|
3798
4316
|
}
|
|
3799
4317
|
delegateEvents(["keydown"]);
|
|
3800
4318
|
|
|
3801
|
-
/**
|
|
3802
|
-
* A class that encapsulates an array of form controls along with their validation logic.
|
|
3803
|
-
*
|
|
3804
|
-
* @template T - An object type representing the shape of a single form control's value.
|
|
3805
|
-
*/
|
|
3806
|
-
class FormArray {
|
|
3807
|
-
/**
|
|
3808
|
-
* An array of array-level validators. Each validator validates the entire array of form control values.
|
|
3809
|
-
* Each element is a ValidatorResult function that returns a validation result for the entire array.
|
|
3810
|
-
*
|
|
3811
|
-
* @private
|
|
3812
|
-
*/
|
|
3813
|
-
internalArrayValidation;
|
|
3814
|
-
/**
|
|
3815
|
-
* An array of control-level validators. Each element is a tuple where the first value is not used
|
|
3816
|
-
* in this class and the second value is an array of validators that validate a single control value.
|
|
3817
|
-
*
|
|
3818
|
-
* @private
|
|
3819
|
-
*/
|
|
3820
|
-
internalValidation;
|
|
3821
|
-
/**
|
|
3822
|
-
* A function to update the current state of control-level validations.
|
|
3823
|
-
*
|
|
3824
|
-
* @private
|
|
3825
|
-
*/
|
|
3826
|
-
setValidation;
|
|
3827
|
-
/**
|
|
3828
|
-
* An array of error arrays. Each inner array holds the errors corresponding to a single form control.
|
|
3829
|
-
*
|
|
3830
|
-
* @private
|
|
3831
|
-
*/
|
|
3832
|
-
errors = [];
|
|
3833
|
-
/**
|
|
3834
|
-
* The current values of the form controls in the array.
|
|
3835
|
-
*
|
|
3836
|
-
* @private
|
|
3837
|
-
*/
|
|
3838
|
-
internalValues;
|
|
3839
|
-
/**
|
|
3840
|
-
* A function to update the current values of the form controls.
|
|
3841
|
-
*
|
|
3842
|
-
* @private
|
|
3843
|
-
*/
|
|
3844
|
-
setValues;
|
|
3845
|
-
// Snapshots of initial validation defs & values for reset purposes
|
|
3846
|
-
_initialValidationDefs;
|
|
3847
|
-
_initialValuesSnapshot;
|
|
3848
|
-
/**
|
|
3849
|
-
* Creates an instance of FormArray.
|
|
3850
|
-
*
|
|
3851
|
-
* @param arrayValidation - A tuple where the first element is an initial array of control-level validation definitions
|
|
3852
|
-
* and the second element is an array of array-level validators.
|
|
3853
|
-
* @param initialValues - Optional initial values for the form controls.
|
|
3854
|
-
*/
|
|
3855
|
-
constructor(arrayValidation, initialValues = []) {
|
|
3856
|
-
const [valid, setValid] = createStore(arrayValidation[0]);
|
|
3857
|
-
const [values, setValues] = createStore(initialValues);
|
|
3858
|
-
this.internalArrayValidation = arrayValidation[1];
|
|
3859
|
-
this.internalValidation = valid;
|
|
3860
|
-
this.setValidation = setValid;
|
|
3861
|
-
this.internalValues = values;
|
|
3862
|
-
this.setValues = setValues;
|
|
3863
|
-
this._initialValidationDefs = [...arrayValidation[0]];
|
|
3864
|
-
this._initialValuesSnapshot = Array.isArray(initialValues) ? Clone(initialValues) : Clone([initialValues]);
|
|
3865
|
-
}
|
|
3866
|
-
/**
|
|
3867
|
-
* Returns true if any validator (array-level or control-level) exists matching the provided errKey.
|
|
3868
|
-
* If no errKey provided, returns true when any validator exists at all.
|
|
3869
|
-
*/
|
|
3870
|
-
hasAnyValidator(errKey) {
|
|
3871
|
-
if (!errKey) {
|
|
3872
|
-
return this.internalArrayValidation.length > 0 || this.internalValidation.some(v => v[1].length > 0);
|
|
3873
|
-
}
|
|
3874
|
-
const inArray = this.internalArrayValidation.some(v => v.errKey === errKey);
|
|
3875
|
-
if (inArray) return true;
|
|
3876
|
-
return this.internalValidation.some(v => v[1].some(val => val.errKey === errKey));
|
|
3877
|
-
}
|
|
3878
|
-
/**
|
|
3879
|
-
* Resets the array to its initial validation definitions and values.
|
|
3880
|
-
* Clears any accumulated errors and added dynamic controls.
|
|
3881
|
-
*/
|
|
3882
|
-
reset() {
|
|
3883
|
-
this.setValidation(() => [...this._initialValidationDefs]);
|
|
3884
|
-
this.setValues(() => Clone(this._initialValuesSnapshot));
|
|
3885
|
-
this.errors = [];
|
|
3886
|
-
}
|
|
3887
|
-
/**
|
|
3888
|
-
* Gets the current values of the form controls in the array.
|
|
3889
|
-
*
|
|
3890
|
-
* @returns A cloned copy of the values array.
|
|
3891
|
-
*/
|
|
3892
|
-
get() {
|
|
3893
|
-
// Return a cloned snapshot so external mutation of returned array/value objects
|
|
3894
|
-
// can't silently mutate internal reactive state or bypass validation/meta tracking.
|
|
3895
|
-
return Clone(this.internalValues);
|
|
3896
|
-
}
|
|
3897
|
-
/**
|
|
3898
|
-
* Gets the value of a specific control in the array.
|
|
3899
|
-
*
|
|
3900
|
-
* @param index - The index of the control.
|
|
3901
|
-
* @returns A cloned copy of the control value.
|
|
3902
|
-
*/
|
|
3903
|
-
getAt(index) {
|
|
3904
|
-
if (index < 0 || index >= this.internalValues.length) {
|
|
3905
|
-
return undefined;
|
|
3906
|
-
}
|
|
3907
|
-
return CloneStore(this.internalValues[index]);
|
|
3908
|
-
}
|
|
3909
|
-
/**
|
|
3910
|
-
* Gets a property value from an object at the specified index.
|
|
3911
|
-
*
|
|
3912
|
-
* @param index - The index of the control.
|
|
3913
|
-
* @param key - The property key to retrieve.
|
|
3914
|
-
* @returns The property value, or undefined if not found.
|
|
3915
|
-
*/
|
|
3916
|
-
getProperty(index, key) {
|
|
3917
|
-
const item = this.getAt(index);
|
|
3918
|
-
return item ? item[key] : undefined;
|
|
3919
|
-
}
|
|
3920
|
-
/**
|
|
3921
|
-
* Sets the values of all controls in the array.
|
|
3922
|
-
*
|
|
3923
|
-
* @param values - The new values for the controls.
|
|
3924
|
-
*/
|
|
3925
|
-
set(values) {
|
|
3926
|
-
this.setValues(Clone(values));
|
|
3927
|
-
}
|
|
3928
|
-
/**
|
|
3929
|
-
* Sets the value of a control at the specified index.
|
|
3930
|
-
*
|
|
3931
|
-
* @param index - The index of the control to update.
|
|
3932
|
-
* @param value - The new value for the control.
|
|
3933
|
-
*/
|
|
3934
|
-
setAt(index, value) {
|
|
3935
|
-
if (index < 0 || index >= this.internalValues.length) {
|
|
3936
|
-
console.error(`Index ${index} out of bounds.`);
|
|
3937
|
-
return;
|
|
3938
|
-
}
|
|
3939
|
-
this.setValues(index, Clone(value));
|
|
3940
|
-
}
|
|
3941
|
-
/**
|
|
3942
|
-
* Sets a property value on an object at the specified index.
|
|
3943
|
-
*
|
|
3944
|
-
* @param index - The index of the control.
|
|
3945
|
-
* @param key - The property key to set.
|
|
3946
|
-
* @param value - The new value for the property.
|
|
3947
|
-
*/
|
|
3948
|
-
setProperty(index, key, value) {
|
|
3949
|
-
if (index < 0 || index >= this.internalValues.length) {
|
|
3950
|
-
console.error(`Index ${index} out of bounds.`);
|
|
3951
|
-
return;
|
|
3952
|
-
}
|
|
3953
|
-
this.setValues(index, oldValue => {
|
|
3954
|
-
const newValue = {
|
|
3955
|
-
...oldValue
|
|
3956
|
-
};
|
|
3957
|
-
newValue[key] = Clone(value);
|
|
3958
|
-
return newValue;
|
|
3959
|
-
});
|
|
3960
|
-
}
|
|
3961
|
-
/**
|
|
3962
|
-
* Removes a control at the specified index.
|
|
3963
|
-
*
|
|
3964
|
-
* @param index - The index of the control to remove.
|
|
3965
|
-
*/
|
|
3966
|
-
remove(index) {
|
|
3967
|
-
// Remove validation
|
|
3968
|
-
this.setValidation(old => {
|
|
3969
|
-
const copy = [...old];
|
|
3970
|
-
copy.splice(index, 1);
|
|
3971
|
-
return copy;
|
|
3972
|
-
});
|
|
3973
|
-
// Remove value
|
|
3974
|
-
this.setValues(old => {
|
|
3975
|
-
const copy = [...old];
|
|
3976
|
-
copy.splice(index, 1);
|
|
3977
|
-
return copy;
|
|
3978
|
-
});
|
|
3979
|
-
// Remove errors
|
|
3980
|
-
if (this.errors.length > index) {
|
|
3981
|
-
this.errors.splice(index, 1);
|
|
3982
|
-
}
|
|
3983
|
-
}
|
|
3984
|
-
/**
|
|
3985
|
-
* Replaces a control at the specified index with new validation and value.
|
|
3986
|
-
*
|
|
3987
|
-
* @param index - The index of the control to replace.
|
|
3988
|
-
* @param controlValidation - The new validation to apply for the control.
|
|
3989
|
-
* @param value - The new value for the control.
|
|
3990
|
-
*/
|
|
3991
|
-
replace(index, controlValidation, value) {
|
|
3992
|
-
this.setValidation(old => {
|
|
3993
|
-
const copy = [...old];
|
|
3994
|
-
copy.splice(index, 1, controlValidation);
|
|
3995
|
-
return copy;
|
|
3996
|
-
});
|
|
3997
|
-
if (value !== undefined) {
|
|
3998
|
-
this.setValues(index, Clone(value));
|
|
3999
|
-
}
|
|
4000
|
-
}
|
|
4001
|
-
/**
|
|
4002
|
-
* Adds a new control to the array with validation and optional value.
|
|
4003
|
-
*
|
|
4004
|
-
* @param controlValidation - The validation definition to add.
|
|
4005
|
-
* @param value - Optional value for the new control.
|
|
4006
|
-
*/
|
|
4007
|
-
add(controlValidation, value) {
|
|
4008
|
-
this.setValidation(old => {
|
|
4009
|
-
return [...old, controlValidation];
|
|
4010
|
-
});
|
|
4011
|
-
this.setValues(old => {
|
|
4012
|
-
return [...old, value ? Clone(value) : {}];
|
|
4013
|
-
});
|
|
4014
|
-
}
|
|
4015
|
-
/**
|
|
4016
|
-
* Checks if any validation errors exist.
|
|
4017
|
-
*
|
|
4018
|
-
* @param index - (Optional) The index of the control to check for errors.
|
|
4019
|
-
* If not provided, it checks the entire form array.
|
|
4020
|
-
* @returns `true` if any errors are found, otherwise `false`.
|
|
4021
|
-
*/
|
|
4022
|
-
hasError(index) {
|
|
4023
|
-
if (isNullish(index)) {
|
|
4024
|
-
// Check errors for all controls if no index is provided.
|
|
4025
|
-
return this.errors.flat().some(error => error.hasError);
|
|
4026
|
-
}
|
|
4027
|
-
// Check errors for a specific control.
|
|
4028
|
-
return this.errors[index].some(error => error.hasError);
|
|
4029
|
-
}
|
|
4030
|
-
/**
|
|
4031
|
-
* Checks if a specific validator error exists for a control at the given index.
|
|
4032
|
-
*
|
|
4033
|
-
* @param index - The index of the control.
|
|
4034
|
-
* @param errKey - The key identifying the specific error to check for.
|
|
4035
|
-
* @returns `true` if the specific error is present, otherwise `false`.
|
|
4036
|
-
*/
|
|
4037
|
-
hasValidator(index, errKey) {
|
|
4038
|
-
return this.errors[index].some(error => error.key === errKey);
|
|
4039
|
-
}
|
|
4040
|
-
/**
|
|
4041
|
-
* Gets all errors for the form array.
|
|
4042
|
-
*
|
|
4043
|
-
* @returns An array of error arrays for each control.
|
|
4044
|
-
*/
|
|
4045
|
-
getErrors() {
|
|
4046
|
-
return Clone(this.errors);
|
|
4047
|
-
}
|
|
4048
|
-
/**
|
|
4049
|
-
* Gets errors for a specific control in the array.
|
|
4050
|
-
*
|
|
4051
|
-
* @param index - The index of the control.
|
|
4052
|
-
* @returns An array of errors for the control, or an empty array if not found.
|
|
4053
|
-
*/
|
|
4054
|
-
getErrorsAt(index) {
|
|
4055
|
-
if (index < 0 || index >= this.errors.length) {
|
|
4056
|
-
return [];
|
|
4057
|
-
}
|
|
4058
|
-
return Clone(this.errors[index]);
|
|
4059
|
-
}
|
|
4060
|
-
/**
|
|
4061
|
-
* Validates the form array using current values.
|
|
4062
|
-
*
|
|
4063
|
-
* @param index - Optional index to validate just one control.
|
|
4064
|
-
* @returns True if validation passes, false otherwise.
|
|
4065
|
-
*/
|
|
4066
|
-
validateCurrent(index) {
|
|
4067
|
-
return this.validate(this.internalValues, index);
|
|
4068
|
-
}
|
|
4069
|
-
/**
|
|
4070
|
-
* Validates the provided form control values.
|
|
4071
|
-
*
|
|
4072
|
-
* @param values - The array of form control values.
|
|
4073
|
-
* @param index - (Optional) The index of a single control to validate.
|
|
4074
|
-
* If not provided, the method validates all controls in the form array.
|
|
4075
|
-
* @returns `true` if all validations pass, otherwise `false`.
|
|
4076
|
-
*/
|
|
4077
|
-
validate(values, index) {
|
|
4078
|
-
if (isNullish(values)) {
|
|
4079
|
-
console.error('Data is null');
|
|
4080
|
-
return false;
|
|
4081
|
-
}
|
|
4082
|
-
// Validate all controls in the form array.
|
|
4083
|
-
if (isNullish(index)) {
|
|
4084
|
-
// Always evaluate array-level validators even if the array is empty
|
|
4085
|
-
const arrayLevelErrors = this.internalArrayValidation.map(validator => ({
|
|
4086
|
-
key: validator.errKey,
|
|
4087
|
-
hasError: !validator.revalidate(values)
|
|
4088
|
-
}));
|
|
4089
|
-
if (values.length === 0) {
|
|
4090
|
-
this.errors = [arrayLevelErrors]; // store array-level errors at index 0 placeholder
|
|
4091
|
-
return this.errors.flat().every(error => !error.hasError);
|
|
4092
|
-
}
|
|
4093
|
-
this.errors = values.map((value, i) => {
|
|
4094
|
-
const controlErrors = this.internalValidation.map(([propKey, validators]) => {
|
|
4095
|
-
const currentVal = value[propKey];
|
|
4096
|
-
return validators.map(validator => ({
|
|
4097
|
-
key: validator.errKey,
|
|
4098
|
-
hasError: !validator.revalidate(currentVal)
|
|
4099
|
-
}));
|
|
4100
|
-
});
|
|
4101
|
-
const arrayErrors = this.internalArrayValidation.map(validator => ({
|
|
4102
|
-
key: validator.errKey,
|
|
4103
|
-
hasError: !validator.revalidate(values)
|
|
4104
|
-
}));
|
|
4105
|
-
const merged = [...controlErrors.flat(), ...arrayErrors];
|
|
4106
|
-
this.errors[i] = merged;
|
|
4107
|
-
return merged;
|
|
4108
|
-
});
|
|
4109
|
-
return this.errors.flat().every(error => !error.hasError);
|
|
4110
|
-
}
|
|
4111
|
-
// Validate a specific control in the form array.
|
|
4112
|
-
const value = values[index];
|
|
4113
|
-
const controlErrors = this.internalValidation.map(([propKey, validators]) => {
|
|
4114
|
-
const currentVal = value[propKey];
|
|
4115
|
-
return validators.map(validator => ({
|
|
4116
|
-
key: validator.errKey,
|
|
4117
|
-
hasError: !validator.revalidate(currentVal)
|
|
4118
|
-
}));
|
|
4119
|
-
});
|
|
4120
|
-
const arrayErrors = this.internalArrayValidation.map(validator => ({
|
|
4121
|
-
key: validator.errKey,
|
|
4122
|
-
hasError: !validator.revalidate(values)
|
|
4123
|
-
}));
|
|
4124
|
-
this.errors[index] = [...controlErrors.flat(), ...arrayErrors];
|
|
4125
|
-
return this.errors[index].every(error => !error.hasError);
|
|
4126
|
-
}
|
|
4127
|
-
}
|
|
4128
|
-
|
|
4129
4319
|
var css_248z$2 = ".formfield-module_formField__w6mH9:focus-within > legend, .formfield-module_has-focus__9ingx > legend {\n top: -8px !important;\n font-size: 0.75rem !important;\n}\n\n.formfield-module_formField__w6mH9 {\n position: relative;\n display: inline-block;\n border-radius: var(--border-radius-md);\n box-sizing: border-box;\n border: none;\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n margin-top: 0px !important;\n margin-bottom: 0px !important;\n}\n.formfield-module_formField__w6mH9 > legend {\n position: absolute;\n left: 12px;\n top: calc(50% - 0.5em);\n font-size: 1rem;\n transition: top 0.25s ease, font-size 0.25s ease;\n pointer-events: none;\n}\n.formfield-module_formField__w6mH9 input::-moz-placeholder, .formfield-module_formField__w6mH9 select::-moz-placeholder {\n opacity: 0 !important;\n -moz-transition: opacity 0.25s ease;\n transition: opacity 0.25s ease;\n}\n.formfield-module_formField__w6mH9 input::placeholder,\n.formfield-module_formField__w6mH9 select::placeholder {\n opacity: 0 !important;\n transition: opacity 0.25s ease;\n}\n.formfield-module_formField__w6mH9 label {\n position: relative;\n top: -0.5rem;\n padding-right: 10px;\n}\n.formfield-module_formField__w6mH9:has(textarea) {\n position: relative;\n margin: 8px;\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n width: auto;\n min-width: 95%;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n padding-bottom: 8px;\n border: none;\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea:focus {\n outline: none;\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_formField__w6mH9:has(textarea) legend {\n height: 24px;\n position: absolute;\n left: 8px;\n transition: all 0.25s ease;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) {\n position: relative;\n height: 48px !important;\n padding: 0px !important;\n width: 100%;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) legend {\n height: 16px;\n max-height: 16px;\n transition: all 0.25s ease;\n top: calc(50% - 1em);\n z-index: 1;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) [is=coles-solid-select] {\n position: absolute;\n left: 0px;\n right: 0px;\n padding: 0px !important;\n margin: 0px !important;\n height: 48px !important;\n border-radius: 4px;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n width: auto;\n min-width: 95%;\n z-index: 0;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) [is=coles-solid-select]:nth-child(n) {\n border-radius: 4px;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) {\n height: 48px;\n position: relative;\n width: 100%;\n margin-top: 16px;\n margin-bottom: 16px;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) legend {\n position: absolute;\n height: 24px;\n left: 8px;\n transition: all 0.25s ease;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) input[type=text] {\n background-color: transparent !important;\n height: 24px;\n border-radius: 4px;\n margin: 8px 0px;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n width: 100%;\n min-width: 95%;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) input[type=text]::-moz-placeholder {\n opacity: 0;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) input[type=text]::placeholder {\n opacity: 0;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) {\n height: 48px;\n position: relative;\n width: 100%;\n margin-top: 16px;\n margin-bottom: 16px;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) legend {\n height: 24px;\n position: absolute;\n left: 8px;\n transition: all 0.25s ease;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) input[type=number] {\n background-color: transparent !important;\n color: var(--on-primary-color, #fff);\n height: 24px;\n border-radius: 4px;\n margin: 8px 0px;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n width: 100%;\n min-width: 95%;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) input[type=number]::-moz-placeholder {\n opacity: 0;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) input[type=number]::placeholder {\n opacity: 0;\n}\n@media screen and (max-width: 768px) {\n .formfield-module_formField__w6mH9 {\n max-width: 75%;\n }\n}\n\n.formfield-module_topMargin__dahW5 {\n margin-top: 12px;\n}\n\n.formfield-module_primary__7BYyQ:has(input[type=text]) input[type=text] {\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(input[type=text]) input[type=text]::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(input[type=text]) input[type=text]::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(input[type=number]) input[type=number] {\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(input[type=number]) input[type=number]::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(input[type=number]) input[type=number]::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has([is=coles-solid-select]) [is=coles-solid-select] {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(textarea) {\n width: 100%;\n height: auto;\n}\n.formfield-module_primary__7BYyQ:has(textarea) textarea {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(textarea) textarea::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(textarea) textarea::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n\n.formfield-module_legendStyle__gnI49 {\n background-color: transparent;\n opacity: var(--text-emphasis-medium, 87%);\n width: 100%;\n transition: all 0.3s ease;\n}\n\n.formfield-module_checkboxPadding__DU1CG {\n padding: 0px;\n padding-bottom: 10px;\n padding-left: 10px;\n padding-right: 10px;\n}\n\n.formfield-module_errorContainer__HR4PL {\n position: relative;\n min-height: 2rem;\n}\n\n.formfield-module_error__wNBh2 {\n position: absolute;\n background: transparent;\n color: var(--error-color, #B00020);\n font-size: 10px;\n}";
|
|
4130
4320
|
var style = {"formField":"formfield-module_formField__w6mH9","has-focus":"formfield-module_has-focus__9ingx","primary":"formfield-module_primary__7BYyQ","legendStyle":"formfield-module_legendStyle__gnI49","errorContainer":"formfield-module_errorContainer__HR4PL","error":"formfield-module_error__wNBh2"};
|
|
4131
4321
|
styleInject(css_248z$2);
|
|
@@ -4156,16 +4346,6 @@ const FormField2 = props => {
|
|
|
4156
4346
|
if (Array.isArray(val) && val.length === 0) return false;
|
|
4157
4347
|
return true;
|
|
4158
4348
|
};
|
|
4159
|
-
// Track dirty meta so legend can float once a field has been modified even if some components
|
|
4160
|
-
// didn't properly synchronize their internal value signals yet.
|
|
4161
|
-
const isDirty = () => {
|
|
4162
|
-
if (!local?.formName) return false;
|
|
4163
|
-
try {
|
|
4164
|
-
return !!formContext?.formGroup?.getMeta?.(local.formName)?.dirty;
|
|
4165
|
-
} catch {
|
|
4166
|
-
return false;
|
|
4167
|
-
}
|
|
4168
|
-
};
|
|
4169
4349
|
const shouldFloat = createMemo(() => {
|
|
4170
4350
|
let currentVal;
|
|
4171
4351
|
const hasFormContext = !!local?.formName && !!formContext?.formGroup;
|
|
@@ -4185,7 +4365,7 @@ const FormField2 = props => {
|
|
|
4185
4365
|
// Float when there is a value, or focused, or meta marked dirty (programmatic set),
|
|
4186
4366
|
// or legacy input marked dirty-on-focus even if still empty (metaDirty && no value yet)
|
|
4187
4367
|
const hasAnyValue = hasValue(currentVal);
|
|
4188
|
-
return hasAnyValue || context?.getFocused?.() || metaDirty
|
|
4368
|
+
return hasAnyValue || context?.getFocused?.() || metaDirty;
|
|
4189
4369
|
});
|
|
4190
4370
|
// Effect: if underlying meta resets to pristine and value cleared, ensure focused state cleared
|
|
4191
4371
|
createEffect(() => {
|
|
@@ -4202,7 +4382,7 @@ const FormField2 = props => {
|
|
|
4202
4382
|
const theChildren = children(() => props.children);
|
|
4203
4383
|
const formErrors = () => {
|
|
4204
4384
|
if (!local?.formName) return [];
|
|
4205
|
-
const allErrors = (formContext?.formGroup
|
|
4385
|
+
const allErrors = (formContext?.formGroup?.getErrors?.(local.formName) ?? []).filter(e => e.hasError);
|
|
4206
4386
|
if (allErrors.length === 0) return [];
|
|
4207
4387
|
let errKeys = allErrors.map(e => e.key);
|
|
4208
4388
|
if (errKeys.includes('required')) {
|
|
@@ -4459,6 +4639,19 @@ class FormGroup {
|
|
|
4459
4639
|
errors;
|
|
4460
4640
|
meta = {};
|
|
4461
4641
|
keys = [];
|
|
4642
|
+
/** Reactive memo that returns a cloned snapshot of the full form state.
|
|
4643
|
+
* FormArray fields resolve via `.get()` (plain array), others via `CloneStore`. */
|
|
4644
|
+
formChangeValue;
|
|
4645
|
+
/** Returns a per-field reactive accessor. Each call creates an independent memo. */
|
|
4646
|
+
fieldChangeValue = key => {
|
|
4647
|
+
return createMemo(() => {
|
|
4648
|
+
const val = this.internalDataSignal[0][key];
|
|
4649
|
+
if (val instanceof FormArray) {
|
|
4650
|
+
return val.get();
|
|
4651
|
+
}
|
|
4652
|
+
return CloneStore(val);
|
|
4653
|
+
});
|
|
4654
|
+
};
|
|
4462
4655
|
constructor(data) {
|
|
4463
4656
|
this.data = data;
|
|
4464
4657
|
const newData = {};
|
|
@@ -4489,6 +4682,20 @@ class FormGroup {
|
|
|
4489
4682
|
this.internalDataSignal = createStore(newData);
|
|
4490
4683
|
this.validators = newValidators;
|
|
4491
4684
|
this.errors = createSignal(newErrors);
|
|
4685
|
+
// Initialise formChangeValue here (after internalDataSignal exists) to avoid
|
|
4686
|
+
// eager evaluation in Solid dev mode when createMemo is used as a field initialiser.
|
|
4687
|
+
this.formChangeValue = createMemo(() => {
|
|
4688
|
+
const current = this.internalDataSignal[0];
|
|
4689
|
+
return this.keys.reduce((acc, key) => {
|
|
4690
|
+
const val = current[key];
|
|
4691
|
+
if (val instanceof FormArray) {
|
|
4692
|
+
acc[key] = val.get();
|
|
4693
|
+
} else {
|
|
4694
|
+
acc[key] = CloneStore(val);
|
|
4695
|
+
}
|
|
4696
|
+
return acc;
|
|
4697
|
+
}, {});
|
|
4698
|
+
});
|
|
4492
4699
|
}
|
|
4493
4700
|
/**
|
|
4494
4701
|
* INTERNAL: returns the reactive internal store reference (DO NOT MUTATE outside FormGroup).
|
|
@@ -4629,6 +4836,42 @@ class FormGroup {
|
|
|
4629
4836
|
markDirty(key) {
|
|
4630
4837
|
this.meta[key].dirty = true;
|
|
4631
4838
|
}
|
|
4839
|
+
/** Returns true if any field in the group has validation errors. */
|
|
4840
|
+
hasAnyError() {
|
|
4841
|
+
const errs = this.errors[0]();
|
|
4842
|
+
for (const k of this.keys) {
|
|
4843
|
+
const val = this.internalDataSignal[0][k];
|
|
4844
|
+
if (val instanceof FormArray) {
|
|
4845
|
+
if (val.hasError()) return true;
|
|
4846
|
+
} else if (errs[k]?.some(e => e.hasError)) {
|
|
4847
|
+
return true;
|
|
4848
|
+
}
|
|
4849
|
+
}
|
|
4850
|
+
return false;
|
|
4851
|
+
}
|
|
4852
|
+
/** Returns true if any field has a validator, optionally matching errKey. */
|
|
4853
|
+
hasAnyValidator(errKey) {
|
|
4854
|
+
for (const k of this.keys) {
|
|
4855
|
+
const val = this.internalDataSignal[0][k];
|
|
4856
|
+
if (val instanceof FormArray) {
|
|
4857
|
+
if (val.hasAnyValidator(errKey)) return true;
|
|
4858
|
+
} else if (!errKey) {
|
|
4859
|
+
if (this.validators[k]?.length > 0) return true;
|
|
4860
|
+
} else {
|
|
4861
|
+
if (this.validators[k]?.some(v => v.errKey === errKey)) return true;
|
|
4862
|
+
}
|
|
4863
|
+
}
|
|
4864
|
+
return false;
|
|
4865
|
+
}
|
|
4866
|
+
/** Returns a flat array of all field errors across the group. */
|
|
4867
|
+
getAllErrors() {
|
|
4868
|
+
const errs = this.errors[0]();
|
|
4869
|
+
const result = [];
|
|
4870
|
+
for (const k of this.keys) {
|
|
4871
|
+
if (errs[k]) result.push(...errs[k]);
|
|
4872
|
+
}
|
|
4873
|
+
return result;
|
|
4874
|
+
}
|
|
4632
4875
|
reset() {
|
|
4633
4876
|
for (const k of this.keys) {
|
|
4634
4877
|
const m = this.meta[k];
|
|
@@ -4675,15 +4918,14 @@ class FormGroup {
|
|
|
4675
4918
|
}
|
|
4676
4919
|
}
|
|
4677
4920
|
/**
|
|
4678
|
-
* Adds
|
|
4921
|
+
* Adds a FormGroup item to a FormArray control.
|
|
4679
4922
|
*
|
|
4680
4923
|
* @param key - The key of the FormArray control
|
|
4681
|
-
* @param
|
|
4682
|
-
* @param value - Optional initial value for the new item
|
|
4924
|
+
* @param group - The FormGroup instance to add
|
|
4683
4925
|
*/
|
|
4684
|
-
addToArray(key,
|
|
4926
|
+
addToArray(key, group) {
|
|
4685
4927
|
if (this.internalDataSignal[0][key] instanceof FormArray) {
|
|
4686
|
-
this.internalDataSignal[0][key].add(
|
|
4928
|
+
this.internalDataSignal[0][key].add(group);
|
|
4687
4929
|
}
|
|
4688
4930
|
}
|
|
4689
4931
|
/**
|
|
@@ -4766,6 +5008,24 @@ class FormGroup {
|
|
|
4766
5008
|
}
|
|
4767
5009
|
}
|
|
4768
5010
|
|
|
5011
|
+
function useFormFieldBinding(key) {
|
|
5012
|
+
const ctx = useFormContext();
|
|
5013
|
+
if (!ctx.formGroup) {
|
|
5014
|
+
throw new Error('useFormFieldBinding requires a FormGroup. It cannot be used with FormArray as the top-level Form data.');
|
|
5015
|
+
}
|
|
5016
|
+
const fg = ctx.formGroup;
|
|
5017
|
+
const value = createMemo(() => fg.getR(key));
|
|
5018
|
+
return {
|
|
5019
|
+
value,
|
|
5020
|
+
setValue: v => fg.set(key, v),
|
|
5021
|
+
errors: () => fg.getErrors(key) ?? [],
|
|
5022
|
+
hasError: () => fg.hasError(key),
|
|
5023
|
+
touched: () => fg.getMeta(key)?.touched,
|
|
5024
|
+
dirty: () => fg.getMeta(key)?.dirty,
|
|
5025
|
+
validate: () => fg.validate(key)
|
|
5026
|
+
};
|
|
5027
|
+
}
|
|
5028
|
+
|
|
4769
5029
|
function createTableContext() {
|
|
4770
5030
|
return createContext({});
|
|
4771
5031
|
}
|
|
@@ -5813,4 +6073,4 @@ const ColeError = props => {
|
|
|
5813
6073
|
return [];
|
|
5814
6074
|
};
|
|
5815
6075
|
|
|
5816
|
-
export { Body, Button, Carousel, Cell, Checkbox, Chip, Chipbar, Column, Container, ExpansionPanel, ColeError as FieldError, Form, FormArray, FormField, FormGroup, Header, Icon, Input, Menu, MenuDropdown, MenuItem, Modal, Option, Radio, RadioGroup, RadioGroupContext, Row, Select, Slide, SnackbarController, TabBar, Table, TextArea, Validators, addSnackbar, addTheme, carouselTitleContext };
|
|
6076
|
+
export { Body, Button, Carousel, Cell, Checkbox, Chip, Chipbar, Column, Container, ExpansionPanel, ColeError as FieldError, Form, FormArray, FormField, FormGroup, Header, Icon, Input, Menu, MenuDropdown, MenuItem, Modal, Option, Radio, RadioGroup, RadioGroupContext, Row, Select, Slide, SnackbarController, TabBar, Table, TextArea, Validators, addSnackbar, addTheme, carouselTitleContext, getEntryAmount, ignoreWindowManager, registerWindowManager, unignoreWindowManager, unregisterWindowManager, useDirectFormBinding, useFormFieldBinding };
|