agentic-zi-ui-schema 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # agentic-zi-ui-schema
2
+
3
+ Shared schema contracts for safe server-driven widgets.
4
+
5
+ - `UiTemplateSchema`: strict UI DSL validation
6
+ - `UiActionSchema`: safe event actions
7
+ - `WidgetRegistrationRequestSchema`: server registration input
8
+ - `AgenticWidgetSchema`: server -> renderer contract
9
+ - hard guard helpers: `countNodes`, `assertWithinLimits`
package/dist/index.d.ts CHANGED
@@ -14,7 +14,7 @@ export declare const UI_LIMITS: {
14
14
  readonly MAX_URL_LEN: 2000;
15
15
  readonly MAX_KEY_LEN: 200;
16
16
  };
17
- export declare const UI_ALLOWED_TAGS: readonly ["a", "article", "aside", "blockquote", "br", "button", "code", "div", "em", "figcaption", "figure", "fieldset", "footer", "form", "h1", "h2", "h3", "h4", "header", "hr", "img", "input", "label", "li", "main", "nav", "ol", "option", "p", "path", "pre", "section", "select", "small", "span", "strong", "svg", "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "tr", "ul"];
17
+ export declare const UI_ALLOWED_TAGS: readonly ["repeat", "a", "article", "aside", "blockquote", "br", "button", "code", "div", "em", "figcaption", "figure", "fieldset", "footer", "form", "h1", "h2", "h3", "h4", "header", "hr", "img", "input", "label", "li", "main", "nav", "ol", "option", "p", "path", "pre", "section", "select", "small", "span", "strong", "svg", "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "tr", "ul"];
18
18
  export declare const UI_ALLOWED_PROPS: readonly ["alt", "aria-label", "aria-controls", "aria-current", "aria-describedby", "aria-disabled", "aria-expanded", "aria-hidden", "aria-invalid", "aria-labelledby", "aria-live", "aria-pressed", "aria-required", "aria-selected", "aria-checked", "aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-valuetext", "aria-busy", "checked", "clipRule", "cols", "cx", "cy", "d", "decoding", "disabled", "fill", "fillRule", "height", "htmlFor", "href", "loading", "max", "maxLength", "min", "minLength", "name", "opacity", "placeholder", "preserveAspectRatio", "rel", "role", "r", "rows", "src", "stroke", "strokeLinecap", "strokeLinejoin", "strokeWidth", "step", "target", "title", "type", "value", "viewBox", "width", "x", "y"];
19
19
  export declare const UI_ALLOWED_EVENTS: readonly ["onClick", "onChange", "onSubmit", "onMouseEnter", "onMouseLeave", "onMouseOver", "onMouseOut", "onMouseDown", "onMouseUp", "onMouseMove", "onFocus", "onBlur"];
20
20
  export declare const UiActionTypeSchema: z.ZodEnum<["FLOW_EVENT", "OPEN_URL", "COPY", "TOAST", "PATCH_STATE"]>;
@@ -1578,4 +1578,448 @@ export declare function countNodes(root: UiNode): {
1578
1578
  depth: number;
1579
1579
  };
1580
1580
  export declare function assertWithinLimits(template: UiTemplate): void;
1581
+ export declare const WidgetMetadataSchema: z.ZodObject<{
1582
+ name: z.ZodString;
1583
+ description: z.ZodOptional<z.ZodString>;
1584
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1585
+ }, "strict", z.ZodTypeAny, {
1586
+ name: string;
1587
+ description?: string | undefined;
1588
+ tags?: string[] | undefined;
1589
+ }, {
1590
+ name: string;
1591
+ description?: string | undefined;
1592
+ tags?: string[] | undefined;
1593
+ }>;
1594
+ export type WidgetMetadata = z.infer<typeof WidgetMetadataSchema>;
1595
+ export declare const WidgetStylesheetSchema: z.ZodOptional<z.ZodObject<{
1596
+ styleId: z.ZodOptional<z.ZodString>;
1597
+ cssText: z.ZodOptional<z.ZodString>;
1598
+ cssUrl: z.ZodOptional<z.ZodString>;
1599
+ classList: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1600
+ }, "strict", z.ZodTypeAny, {
1601
+ styleId?: string | undefined;
1602
+ cssText?: string | undefined;
1603
+ cssUrl?: string | undefined;
1604
+ classList?: string[] | undefined;
1605
+ }, {
1606
+ styleId?: string | undefined;
1607
+ cssText?: string | undefined;
1608
+ cssUrl?: string | undefined;
1609
+ classList?: string[] | undefined;
1610
+ }>>;
1611
+ export type WidgetStylesheet = z.infer<typeof WidgetStylesheetSchema>;
1612
+ export declare const AgenticWidgetSchema: z.ZodObject<{
1613
+ schema: z.ZodLiteral<"agentic.widget.v1">;
1614
+ widgetId: z.ZodString;
1615
+ template: z.ZodObject<{
1616
+ schema: z.ZodLiteral<"ui.v1">;
1617
+ root: z.ZodType<any, z.ZodTypeDef, any>;
1618
+ }, "strict", z.ZodTypeAny, {
1619
+ schema: "ui.v1";
1620
+ root?: any;
1621
+ }, {
1622
+ schema: "ui.v1";
1623
+ root?: any;
1624
+ }>;
1625
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1626
+ metadata: z.ZodOptional<z.ZodObject<{
1627
+ name: z.ZodString;
1628
+ description: z.ZodOptional<z.ZodString>;
1629
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1630
+ }, "strict", z.ZodTypeAny, {
1631
+ name: string;
1632
+ description?: string | undefined;
1633
+ tags?: string[] | undefined;
1634
+ }, {
1635
+ name: string;
1636
+ description?: string | undefined;
1637
+ tags?: string[] | undefined;
1638
+ }>>;
1639
+ policy: z.ZodOptional<z.ZodObject<{
1640
+ allowedTags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1641
+ allowedProps: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1642
+ allowedActions: z.ZodOptional<z.ZodArray<z.ZodEnum<["FLOW_EVENT", "OPEN_URL", "COPY", "TOAST", "PATCH_STATE"]>, "many">>;
1643
+ maxNodes: z.ZodOptional<z.ZodNumber>;
1644
+ maxDepth: z.ZodOptional<z.ZodNumber>;
1645
+ }, "strict", z.ZodTypeAny, {
1646
+ allowedTags?: string[] | undefined;
1647
+ allowedProps?: string[] | undefined;
1648
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1649
+ maxNodes?: number | undefined;
1650
+ maxDepth?: number | undefined;
1651
+ }, {
1652
+ allowedTags?: string[] | undefined;
1653
+ allowedProps?: string[] | undefined;
1654
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1655
+ maxNodes?: number | undefined;
1656
+ maxDepth?: number | undefined;
1657
+ }>>;
1658
+ stylesheet: z.ZodOptional<z.ZodObject<{
1659
+ styleId: z.ZodOptional<z.ZodString>;
1660
+ cssText: z.ZodOptional<z.ZodString>;
1661
+ cssUrl: z.ZodOptional<z.ZodString>;
1662
+ classList: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1663
+ }, "strict", z.ZodTypeAny, {
1664
+ styleId?: string | undefined;
1665
+ cssText?: string | undefined;
1666
+ cssUrl?: string | undefined;
1667
+ classList?: string[] | undefined;
1668
+ }, {
1669
+ styleId?: string | undefined;
1670
+ cssText?: string | undefined;
1671
+ cssUrl?: string | undefined;
1672
+ classList?: string[] | undefined;
1673
+ }>>;
1674
+ }, "strict", z.ZodTypeAny, {
1675
+ widgetId: string;
1676
+ schema: "agentic.widget.v1";
1677
+ template: {
1678
+ schema: "ui.v1";
1679
+ root?: any;
1680
+ };
1681
+ policy?: {
1682
+ allowedTags?: string[] | undefined;
1683
+ allowedProps?: string[] | undefined;
1684
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1685
+ maxNodes?: number | undefined;
1686
+ maxDepth?: number | undefined;
1687
+ } | undefined;
1688
+ data?: Record<string, unknown> | undefined;
1689
+ metadata?: {
1690
+ name: string;
1691
+ description?: string | undefined;
1692
+ tags?: string[] | undefined;
1693
+ } | undefined;
1694
+ stylesheet?: {
1695
+ styleId?: string | undefined;
1696
+ cssText?: string | undefined;
1697
+ cssUrl?: string | undefined;
1698
+ classList?: string[] | undefined;
1699
+ } | undefined;
1700
+ }, {
1701
+ widgetId: string;
1702
+ schema: "agentic.widget.v1";
1703
+ template: {
1704
+ schema: "ui.v1";
1705
+ root?: any;
1706
+ };
1707
+ policy?: {
1708
+ allowedTags?: string[] | undefined;
1709
+ allowedProps?: string[] | undefined;
1710
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1711
+ maxNodes?: number | undefined;
1712
+ maxDepth?: number | undefined;
1713
+ } | undefined;
1714
+ data?: Record<string, unknown> | undefined;
1715
+ metadata?: {
1716
+ name: string;
1717
+ description?: string | undefined;
1718
+ tags?: string[] | undefined;
1719
+ } | undefined;
1720
+ stylesheet?: {
1721
+ styleId?: string | undefined;
1722
+ cssText?: string | undefined;
1723
+ cssUrl?: string | undefined;
1724
+ classList?: string[] | undefined;
1725
+ } | undefined;
1726
+ }>;
1727
+ export type AgenticWidget = z.infer<typeof AgenticWidgetSchema>;
1728
+ export declare const WidgetRegistrationRequestSchema: z.ZodObject<{
1729
+ id: z.ZodOptional<z.ZodString>;
1730
+ template: z.ZodObject<{
1731
+ schema: z.ZodLiteral<"ui.v1">;
1732
+ root: z.ZodType<any, z.ZodTypeDef, any>;
1733
+ }, "strict", z.ZodTypeAny, {
1734
+ schema: "ui.v1";
1735
+ root?: any;
1736
+ }, {
1737
+ schema: "ui.v1";
1738
+ root?: any;
1739
+ }>;
1740
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1741
+ metadata: z.ZodObject<{
1742
+ name: z.ZodString;
1743
+ description: z.ZodOptional<z.ZodString>;
1744
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1745
+ }, "strict", z.ZodTypeAny, {
1746
+ name: string;
1747
+ description?: string | undefined;
1748
+ tags?: string[] | undefined;
1749
+ }, {
1750
+ name: string;
1751
+ description?: string | undefined;
1752
+ tags?: string[] | undefined;
1753
+ }>;
1754
+ policy: z.ZodOptional<z.ZodObject<{
1755
+ allowedTags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1756
+ allowedProps: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1757
+ allowedActions: z.ZodOptional<z.ZodArray<z.ZodEnum<["FLOW_EVENT", "OPEN_URL", "COPY", "TOAST", "PATCH_STATE"]>, "many">>;
1758
+ maxNodes: z.ZodOptional<z.ZodNumber>;
1759
+ maxDepth: z.ZodOptional<z.ZodNumber>;
1760
+ }, "strict", z.ZodTypeAny, {
1761
+ allowedTags?: string[] | undefined;
1762
+ allowedProps?: string[] | undefined;
1763
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1764
+ maxNodes?: number | undefined;
1765
+ maxDepth?: number | undefined;
1766
+ }, {
1767
+ allowedTags?: string[] | undefined;
1768
+ allowedProps?: string[] | undefined;
1769
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1770
+ maxNodes?: number | undefined;
1771
+ maxDepth?: number | undefined;
1772
+ }>>;
1773
+ replaceIfExists: z.ZodOptional<z.ZodBoolean>;
1774
+ }, "strict", z.ZodTypeAny, {
1775
+ template: {
1776
+ schema: "ui.v1";
1777
+ root?: any;
1778
+ };
1779
+ metadata: {
1780
+ name: string;
1781
+ description?: string | undefined;
1782
+ tags?: string[] | undefined;
1783
+ };
1784
+ id?: string | undefined;
1785
+ policy?: {
1786
+ allowedTags?: string[] | undefined;
1787
+ allowedProps?: string[] | undefined;
1788
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1789
+ maxNodes?: number | undefined;
1790
+ maxDepth?: number | undefined;
1791
+ } | undefined;
1792
+ data?: Record<string, unknown> | undefined;
1793
+ replaceIfExists?: boolean | undefined;
1794
+ }, {
1795
+ template: {
1796
+ schema: "ui.v1";
1797
+ root?: any;
1798
+ };
1799
+ metadata: {
1800
+ name: string;
1801
+ description?: string | undefined;
1802
+ tags?: string[] | undefined;
1803
+ };
1804
+ id?: string | undefined;
1805
+ policy?: {
1806
+ allowedTags?: string[] | undefined;
1807
+ allowedProps?: string[] | undefined;
1808
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1809
+ maxNodes?: number | undefined;
1810
+ maxDepth?: number | undefined;
1811
+ } | undefined;
1812
+ data?: Record<string, unknown> | undefined;
1813
+ replaceIfExists?: boolean | undefined;
1814
+ }>;
1815
+ export type WidgetRegistrationRequest = z.infer<typeof WidgetRegistrationRequestSchema>;
1816
+ export declare const WidgetRecordSchema: z.ZodObject<{
1817
+ schema: z.ZodLiteral<"agentic.widget.record.v1">;
1818
+ id: z.ZodString;
1819
+ version: z.ZodNumber;
1820
+ widget: z.ZodObject<{
1821
+ schema: z.ZodLiteral<"agentic.widget.v1">;
1822
+ widgetId: z.ZodString;
1823
+ template: z.ZodObject<{
1824
+ schema: z.ZodLiteral<"ui.v1">;
1825
+ root: z.ZodType<any, z.ZodTypeDef, any>;
1826
+ }, "strict", z.ZodTypeAny, {
1827
+ schema: "ui.v1";
1828
+ root?: any;
1829
+ }, {
1830
+ schema: "ui.v1";
1831
+ root?: any;
1832
+ }>;
1833
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1834
+ metadata: z.ZodOptional<z.ZodObject<{
1835
+ name: z.ZodString;
1836
+ description: z.ZodOptional<z.ZodString>;
1837
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1838
+ }, "strict", z.ZodTypeAny, {
1839
+ name: string;
1840
+ description?: string | undefined;
1841
+ tags?: string[] | undefined;
1842
+ }, {
1843
+ name: string;
1844
+ description?: string | undefined;
1845
+ tags?: string[] | undefined;
1846
+ }>>;
1847
+ policy: z.ZodOptional<z.ZodObject<{
1848
+ allowedTags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1849
+ allowedProps: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1850
+ allowedActions: z.ZodOptional<z.ZodArray<z.ZodEnum<["FLOW_EVENT", "OPEN_URL", "COPY", "TOAST", "PATCH_STATE"]>, "many">>;
1851
+ maxNodes: z.ZodOptional<z.ZodNumber>;
1852
+ maxDepth: z.ZodOptional<z.ZodNumber>;
1853
+ }, "strict", z.ZodTypeAny, {
1854
+ allowedTags?: string[] | undefined;
1855
+ allowedProps?: string[] | undefined;
1856
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1857
+ maxNodes?: number | undefined;
1858
+ maxDepth?: number | undefined;
1859
+ }, {
1860
+ allowedTags?: string[] | undefined;
1861
+ allowedProps?: string[] | undefined;
1862
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1863
+ maxNodes?: number | undefined;
1864
+ maxDepth?: number | undefined;
1865
+ }>>;
1866
+ stylesheet: z.ZodOptional<z.ZodObject<{
1867
+ styleId: z.ZodOptional<z.ZodString>;
1868
+ cssText: z.ZodOptional<z.ZodString>;
1869
+ cssUrl: z.ZodOptional<z.ZodString>;
1870
+ classList: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1871
+ }, "strict", z.ZodTypeAny, {
1872
+ styleId?: string | undefined;
1873
+ cssText?: string | undefined;
1874
+ cssUrl?: string | undefined;
1875
+ classList?: string[] | undefined;
1876
+ }, {
1877
+ styleId?: string | undefined;
1878
+ cssText?: string | undefined;
1879
+ cssUrl?: string | undefined;
1880
+ classList?: string[] | undefined;
1881
+ }>>;
1882
+ }, "strict", z.ZodTypeAny, {
1883
+ widgetId: string;
1884
+ schema: "agentic.widget.v1";
1885
+ template: {
1886
+ schema: "ui.v1";
1887
+ root?: any;
1888
+ };
1889
+ policy?: {
1890
+ allowedTags?: string[] | undefined;
1891
+ allowedProps?: string[] | undefined;
1892
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1893
+ maxNodes?: number | undefined;
1894
+ maxDepth?: number | undefined;
1895
+ } | undefined;
1896
+ data?: Record<string, unknown> | undefined;
1897
+ metadata?: {
1898
+ name: string;
1899
+ description?: string | undefined;
1900
+ tags?: string[] | undefined;
1901
+ } | undefined;
1902
+ stylesheet?: {
1903
+ styleId?: string | undefined;
1904
+ cssText?: string | undefined;
1905
+ cssUrl?: string | undefined;
1906
+ classList?: string[] | undefined;
1907
+ } | undefined;
1908
+ }, {
1909
+ widgetId: string;
1910
+ schema: "agentic.widget.v1";
1911
+ template: {
1912
+ schema: "ui.v1";
1913
+ root?: any;
1914
+ };
1915
+ policy?: {
1916
+ allowedTags?: string[] | undefined;
1917
+ allowedProps?: string[] | undefined;
1918
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1919
+ maxNodes?: number | undefined;
1920
+ maxDepth?: number | undefined;
1921
+ } | undefined;
1922
+ data?: Record<string, unknown> | undefined;
1923
+ metadata?: {
1924
+ name: string;
1925
+ description?: string | undefined;
1926
+ tags?: string[] | undefined;
1927
+ } | undefined;
1928
+ stylesheet?: {
1929
+ styleId?: string | undefined;
1930
+ cssText?: string | undefined;
1931
+ cssUrl?: string | undefined;
1932
+ classList?: string[] | undefined;
1933
+ } | undefined;
1934
+ }>;
1935
+ createdAt: z.ZodString;
1936
+ updatedAt: z.ZodString;
1937
+ }, "strict", z.ZodTypeAny, {
1938
+ id: string;
1939
+ schema: "agentic.widget.record.v1";
1940
+ version: number;
1941
+ widget: {
1942
+ widgetId: string;
1943
+ schema: "agentic.widget.v1";
1944
+ template: {
1945
+ schema: "ui.v1";
1946
+ root?: any;
1947
+ };
1948
+ policy?: {
1949
+ allowedTags?: string[] | undefined;
1950
+ allowedProps?: string[] | undefined;
1951
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1952
+ maxNodes?: number | undefined;
1953
+ maxDepth?: number | undefined;
1954
+ } | undefined;
1955
+ data?: Record<string, unknown> | undefined;
1956
+ metadata?: {
1957
+ name: string;
1958
+ description?: string | undefined;
1959
+ tags?: string[] | undefined;
1960
+ } | undefined;
1961
+ stylesheet?: {
1962
+ styleId?: string | undefined;
1963
+ cssText?: string | undefined;
1964
+ cssUrl?: string | undefined;
1965
+ classList?: string[] | undefined;
1966
+ } | undefined;
1967
+ };
1968
+ createdAt: string;
1969
+ updatedAt: string;
1970
+ }, {
1971
+ id: string;
1972
+ schema: "agentic.widget.record.v1";
1973
+ version: number;
1974
+ widget: {
1975
+ widgetId: string;
1976
+ schema: "agentic.widget.v1";
1977
+ template: {
1978
+ schema: "ui.v1";
1979
+ root?: any;
1980
+ };
1981
+ policy?: {
1982
+ allowedTags?: string[] | undefined;
1983
+ allowedProps?: string[] | undefined;
1984
+ allowedActions?: ("FLOW_EVENT" | "OPEN_URL" | "COPY" | "TOAST" | "PATCH_STATE")[] | undefined;
1985
+ maxNodes?: number | undefined;
1986
+ maxDepth?: number | undefined;
1987
+ } | undefined;
1988
+ data?: Record<string, unknown> | undefined;
1989
+ metadata?: {
1990
+ name: string;
1991
+ description?: string | undefined;
1992
+ tags?: string[] | undefined;
1993
+ } | undefined;
1994
+ stylesheet?: {
1995
+ styleId?: string | undefined;
1996
+ cssText?: string | undefined;
1997
+ cssUrl?: string | undefined;
1998
+ classList?: string[] | undefined;
1999
+ } | undefined;
2000
+ };
2001
+ createdAt: string;
2002
+ updatedAt: string;
2003
+ }>;
2004
+ export type WidgetRecord = z.infer<typeof WidgetRecordSchema>;
2005
+ export declare const WidgetListItemSchema: z.ZodObject<{
2006
+ id: z.ZodString;
2007
+ name: z.ZodString;
2008
+ version: z.ZodNumber;
2009
+ updatedAt: z.ZodString;
2010
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
2011
+ }, "strict", z.ZodTypeAny, {
2012
+ name: string;
2013
+ id: string;
2014
+ version: number;
2015
+ updatedAt: string;
2016
+ tags?: string[] | undefined;
2017
+ }, {
2018
+ name: string;
2019
+ id: string;
2020
+ version: number;
2021
+ updatedAt: string;
2022
+ tags?: string[] | undefined;
2023
+ }>;
2024
+ export type WidgetListItem = z.infer<typeof WidgetListItemSchema>;
1581
2025
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ export const UI_LIMITS = {
16
16
  MAX_KEY_LEN: 200,
17
17
  };
18
18
  export const UI_ALLOWED_TAGS = [
19
+ "repeat",
19
20
  "a",
20
21
  "article",
21
22
  "aside",
@@ -509,3 +510,60 @@ export function assertWithinLimits(template) {
509
510
  throw new Error(`UI template too deep: depth=${depth} > ${UI_LIMITS.MAX_DEPTH}`);
510
511
  }
511
512
  }
513
+ // ------------------ Widget transport contracts ------------------
514
+ export const WidgetMetadataSchema = z
515
+ .object({
516
+ name: z.string().min(1).max(120),
517
+ description: z.string().max(2000).optional(),
518
+ tags: z.array(z.string().min(1).max(50)).max(20).optional(),
519
+ })
520
+ .strict();
521
+ export const WidgetStylesheetSchema = z
522
+ .object({
523
+ styleId: zSafeId.optional(),
524
+ cssText: z.string().max(2000000).optional(),
525
+ cssUrl: z.string().max(UI_LIMITS.MAX_URL_LEN).optional(),
526
+ classList: z.array(z.string().min(1).max(200)).max(10000).optional(),
527
+ })
528
+ .strict()
529
+ .optional();
530
+ export const AgenticWidgetSchema = z
531
+ .object({
532
+ schema: z.literal("agentic.widget.v1"),
533
+ widgetId: zSafeId,
534
+ template: UiTemplateSchema,
535
+ data: z.record(z.string(), z.unknown()).optional(),
536
+ metadata: WidgetMetadataSchema.optional(),
537
+ policy: WidgetPolicySchema,
538
+ stylesheet: WidgetStylesheetSchema,
539
+ })
540
+ .strict();
541
+ export const WidgetRegistrationRequestSchema = z
542
+ .object({
543
+ id: zSafeId.optional(),
544
+ template: UiTemplateSchema,
545
+ data: z.record(z.string(), z.unknown()).optional(),
546
+ metadata: WidgetMetadataSchema,
547
+ policy: WidgetPolicySchema,
548
+ replaceIfExists: z.boolean().optional(),
549
+ })
550
+ .strict();
551
+ export const WidgetRecordSchema = z
552
+ .object({
553
+ schema: z.literal("agentic.widget.record.v1"),
554
+ id: zSafeId,
555
+ version: z.number().int().min(1),
556
+ widget: AgenticWidgetSchema,
557
+ createdAt: z.string(),
558
+ updatedAt: z.string(),
559
+ })
560
+ .strict();
561
+ export const WidgetListItemSchema = z
562
+ .object({
563
+ id: zSafeId,
564
+ name: z.string().min(1).max(120),
565
+ version: z.number().int().min(1),
566
+ updatedAt: z.string(),
567
+ tags: z.array(z.string().min(1).max(50)).max(20).optional(),
568
+ })
569
+ .strict();
package/package.json CHANGED
@@ -1,12 +1,22 @@
1
1
  {
2
2
  "name": "agentic-zi-ui-schema",
3
- "version": "0.0.2",
3
+ "version": "0.1.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "private": false,
7
7
  "scripts": {
8
8
  "dev": "tsc -w",
9
- "build": "tsc"
9
+ "build": "tsc",
10
+ "prepublishOnly": "npm run build",
11
+ "npm:login": "npm login --registry https://registry.npmjs.org/",
12
+ "publish:public": "(npm whoami --registry https://registry.npmjs.org/ >/dev/null 2>&1 || npm run npm:login) && npm_config_cache=./.npm-cache npm publish --registry https://registry.npmjs.org/ --access public"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "devDependencies": {
19
+ "typescript": "~5.9.3"
10
20
  },
11
21
  "dependencies": {
12
22
  "zod": "^3.23.8"
package/src/index.ts DELETED
@@ -1,576 +0,0 @@
1
- import { z } from "zod";
2
-
3
- /**
4
- * ui.v1 — a safe, declarative UI schema.
5
- * - No executable JS
6
- * - Events map to action descriptors
7
- * - Client uses allowlists to render
8
- */
9
-
10
- // ------------------ Guardrails ------------------
11
-
12
- export const UI_LIMITS = {
13
- MAX_NODES: 500,
14
- MAX_DEPTH: 30,
15
- MAX_TEXT_LEN: 10_000,
16
- MAX_CLASSNAME_LEN: 1_000,
17
- MAX_ID_LEN: 200,
18
- MAX_URL_LEN: 2_000,
19
- MAX_KEY_LEN: 200,
20
- } as const;
21
-
22
- export const UI_ALLOWED_TAGS = [
23
- "a",
24
- "article",
25
- "aside",
26
- "blockquote",
27
- "br",
28
- "button",
29
- "code",
30
- "div",
31
- "em",
32
- "figcaption",
33
- "figure",
34
- "fieldset",
35
- "footer",
36
- "form",
37
- "h1",
38
- "h2",
39
- "h3",
40
- "h4",
41
- "header",
42
- "hr",
43
- "img",
44
- "input",
45
- "label",
46
- "li",
47
- "main",
48
- "nav",
49
- "ol",
50
- "option",
51
- "p",
52
- "path",
53
- "pre",
54
- "section",
55
- "select",
56
- "small",
57
- "span",
58
- "strong",
59
- "svg",
60
- "table",
61
- "tbody",
62
- "td",
63
- "textarea",
64
- "tfoot",
65
- "th",
66
- "thead",
67
- "tr",
68
- "ul",
69
- ] as const;
70
-
71
- export const UI_ALLOWED_PROPS = [
72
- "alt",
73
- "aria-label",
74
- "aria-controls",
75
- "aria-current",
76
- "aria-describedby",
77
- "aria-disabled",
78
- "aria-expanded",
79
- "aria-hidden",
80
- "aria-invalid",
81
- "aria-labelledby",
82
- "aria-live",
83
- "aria-pressed",
84
- "aria-required",
85
- "aria-selected",
86
- "aria-checked",
87
- "aria-valuemax",
88
- "aria-valuemin",
89
- "aria-valuenow",
90
- "aria-valuetext",
91
- "aria-busy",
92
- "checked",
93
- "clipRule",
94
- "cols",
95
- "cx",
96
- "cy",
97
- "d",
98
- "decoding",
99
- "disabled",
100
- "fill",
101
- "fillRule",
102
- "height",
103
- "htmlFor",
104
- "href",
105
- "loading",
106
- "max",
107
- "maxLength",
108
- "min",
109
- "minLength",
110
- "name",
111
- "opacity",
112
- "placeholder",
113
- "preserveAspectRatio",
114
- "rel",
115
- "role",
116
- "r",
117
- "rows",
118
- "src",
119
- "stroke",
120
- "strokeLinecap",
121
- "strokeLinejoin",
122
- "strokeWidth",
123
- "step",
124
- "target",
125
- "title",
126
- "type",
127
- "value",
128
- "viewBox",
129
- "width",
130
- "x",
131
- "y",
132
- ] as const;
133
-
134
- export const UI_ALLOWED_EVENTS = [
135
- "onClick",
136
- "onChange",
137
- "onSubmit",
138
- "onMouseEnter",
139
- "onMouseLeave",
140
- "onMouseOver",
141
- "onMouseOut",
142
- "onMouseDown",
143
- "onMouseUp",
144
- "onMouseMove",
145
- "onFocus",
146
- "onBlur",
147
- ] as const;
148
-
149
- const zSafeId = z.string().min(1).max(UI_LIMITS.MAX_ID_LEN);
150
- const zSafeText = z.string().max(UI_LIMITS.MAX_TEXT_LEN);
151
- const zSafeClassName = z.string().max(UI_LIMITS.MAX_CLASSNAME_LEN);
152
- const zSafeKey = z.string().min(1).max(UI_LIMITS.MAX_KEY_LEN);
153
- const zSafePropValue = z.union([z.string(), z.number(), z.boolean()]);
154
-
155
- const UI_BASE_PROP_KEYS = new Set<string>(UI_ALLOWED_PROPS);
156
-
157
- // ------------------ Actions ------------------
158
-
159
- export const UiActionTypeSchema = z.enum([
160
- "FLOW_EVENT",
161
- "OPEN_URL",
162
- "COPY",
163
- "TOAST",
164
- "PATCH_STATE",
165
- ]);
166
-
167
- export type UiActionType = z.infer<typeof UiActionTypeSchema>;
168
-
169
- export const UiActionSchema = z.discriminatedUnion("type", [
170
- z.object({
171
- type: z.literal("FLOW_EVENT"),
172
- name: z.string().min(1).max(200),
173
- payload: z.record(z.string(), z.unknown()).optional(),
174
- }),
175
- z.object({
176
- type: z.literal("OPEN_URL"),
177
- url: z.string().min(1).max(UI_LIMITS.MAX_URL_LEN),
178
- target: z.enum(["_blank", "_self"]).optional(),
179
- }),
180
- z.object({
181
- type: z.literal("COPY"),
182
- text: zSafeText,
183
- }),
184
- z.object({
185
- type: z.literal("TOAST"),
186
- message: z.string().min(1).max(500),
187
- level: z.enum(["info", "success", "warning", "error"]).optional(),
188
- }),
189
- z.object({
190
- // Local component state patch. (POC: flat key/value)
191
- type: z.literal("PATCH_STATE"),
192
- key: z.string().min(1).max(UI_LIMITS.MAX_KEY_LEN),
193
- valueFrom: z
194
- .enum(["event.target.value", "event.target.checked"])
195
- .optional(),
196
- value: z.unknown().optional(),
197
- }),
198
- ]);
199
-
200
- export type UiAction = z.infer<typeof UiActionSchema>;
201
-
202
- // ------------------ Events ------------------
203
-
204
- export const UiEventMapSchema = z
205
- .object({
206
- onClick: UiActionSchema.optional(),
207
- onChange: UiActionSchema.optional(),
208
- onSubmit: UiActionSchema.optional(),
209
- onMouseEnter: UiActionSchema.optional(),
210
- onMouseLeave: UiActionSchema.optional(),
211
- onMouseOver: UiActionSchema.optional(),
212
- onMouseOut: UiActionSchema.optional(),
213
- onMouseDown: UiActionSchema.optional(),
214
- onMouseUp: UiActionSchema.optional(),
215
- onMouseMove: UiActionSchema.optional(),
216
- onFocus: UiActionSchema.optional(),
217
- onBlur: UiActionSchema.optional(),
218
- })
219
- .strict();
220
-
221
- export type UiEventMap = z.infer<typeof UiEventMapSchema>;
222
-
223
- // ------------------ Node schema ------------------
224
-
225
- /**
226
- * We keep props limited. No dangerouslySetInnerHTML.
227
- * You can expand allowed props gradually.
228
- */
229
- const UiPropsSchema = z
230
- .object({
231
- // common
232
- title: z.string().max(500).optional(),
233
- role: z.string().max(200).optional(),
234
- "aria-label": z.string().max(200).optional(),
235
- "aria-controls": z.string().max(200).optional(),
236
- "aria-current": zSafePropValue.optional(),
237
- "aria-describedby": z.string().max(200).optional(),
238
- "aria-disabled": zSafePropValue.optional(),
239
- "aria-expanded": zSafePropValue.optional(),
240
- "aria-hidden": zSafePropValue.optional(),
241
- "aria-invalid": zSafePropValue.optional(),
242
- "aria-labelledby": z.string().max(200).optional(),
243
- "aria-live": z.string().max(50).optional(),
244
- "aria-pressed": zSafePropValue.optional(),
245
- "aria-required": zSafePropValue.optional(),
246
- "aria-selected": zSafePropValue.optional(),
247
- "aria-checked": zSafePropValue.optional(),
248
- "aria-valuemax": zSafePropValue.optional(),
249
- "aria-valuemin": zSafePropValue.optional(),
250
- "aria-valuenow": zSafePropValue.optional(),
251
- "aria-valuetext": z.string().max(200).optional(),
252
- "aria-busy": zSafePropValue.optional(),
253
-
254
- // input-ish
255
- placeholder: z.string().max(200).optional(),
256
- type: z.string().max(50).optional(),
257
- name: z.string().max(200).optional(),
258
- value: z.union([z.string(), z.number(), z.boolean()]).optional(),
259
- checked: z.union([z.boolean(), z.string()]).optional(),
260
- disabled: z.union([z.boolean(), z.string()]).optional(),
261
-
262
- // links + media
263
- href: z.string().max(UI_LIMITS.MAX_URL_LEN).optional(),
264
- target: z.enum(["_blank", "_self"]).optional(),
265
- rel: z.string().max(200).optional(),
266
- src: z.string().max(UI_LIMITS.MAX_URL_LEN).optional(),
267
- alt: z.string().max(500).optional(),
268
- loading: z.enum(["eager", "lazy"]).optional(),
269
- decoding: z.enum(["auto", "async", "sync"]).optional(),
270
-
271
- // sizing + constraints
272
- width: z.union([z.string(), z.number()]).optional(),
273
- height: z.union([z.string(), z.number()]).optional(),
274
- rows: z.number().int().min(1).max(1000).optional(),
275
- cols: z.number().int().min(1).max(2000).optional(),
276
- min: z.union([z.string(), z.number()]).optional(),
277
- max: z.union([z.string(), z.number()]).optional(),
278
- step: z.union([z.string(), z.number()]).optional(),
279
- minLength: z.number().int().min(0).max(10000).optional(),
280
- maxLength: z.number().int().min(0).max(10000).optional(),
281
-
282
- // label
283
- htmlFor: z.string().max(200).optional(),
284
-
285
- // svg-ish
286
- viewBox: z.string().max(200).optional(),
287
- preserveAspectRatio: z.string().max(200).optional(),
288
- fill: z.string().max(200).optional(),
289
- fillRule: z.string().max(50).optional(),
290
- clipRule: z.string().max(50).optional(),
291
- stroke: z.string().max(200).optional(),
292
- strokeWidth: z.union([z.string(), z.number()]).optional(),
293
- strokeLinecap: z.string().max(50).optional(),
294
- strokeLinejoin: z.string().max(50).optional(),
295
- d: z.string().max(2000).optional(),
296
- cx: z.union([z.string(), z.number()]).optional(),
297
- cy: z.union([z.string(), z.number()]).optional(),
298
- r: z.union([z.string(), z.number()]).optional(),
299
- x: z.union([z.string(), z.number()]).optional(),
300
- y: z.union([z.string(), z.number()]).optional(),
301
- opacity: z.union([z.string(), z.number()]).optional(),
302
- })
303
- .catchall(zSafePropValue)
304
- .superRefine((props, ctx) => {
305
- if (!props) return;
306
- for (const key of Object.keys(props)) {
307
- if (UI_BASE_PROP_KEYS.has(key)) continue;
308
- if (key.startsWith("aria-") || key.startsWith("data-")) {
309
- if (key.length > UI_LIMITS.MAX_KEY_LEN) {
310
- ctx.addIssue({
311
- code: z.ZodIssueCode.custom,
312
- message: `Prop key too long: ${key}`,
313
- path: [key],
314
- });
315
- }
316
- continue;
317
- }
318
- ctx.addIssue({
319
- code: z.ZodIssueCode.custom,
320
- message: `Unsupported prop: ${key}`,
321
- path: [key],
322
- });
323
- }
324
- })
325
- .optional();
326
-
327
- export const UiBindSchema = z
328
- .object({
329
- // bind node value/checked to local state key
330
- valueKey: zSafeKey.optional(),
331
- checkedKey: zSafeKey.optional(),
332
- })
333
- .strict()
334
- .optional();
335
-
336
- export type UiBind = z.infer<typeof UiBindSchema>;
337
-
338
- export const UiNodeSchema: z.ZodType<any> = z.lazy(() =>
339
- z
340
- .object({
341
- id: zSafeId.optional(),
342
- type: z.string().min(1).max(50), // allowlist enforced on client
343
- className: zSafeClassName.optional(),
344
- props: UiPropsSchema,
345
- events: UiEventMapSchema.optional(),
346
- bind: UiBindSchema,
347
- // repeat support
348
- items: z.string().min(1).max(200).optional(),
349
- as: zSafeKey.optional(),
350
- indexAs: zSafeKey.optional(),
351
- widgetId: zSafeId.optional(),
352
- widgetProps: z.record(zSafeKey, z.unknown()).optional(),
353
- slots: z
354
- .record(
355
- zSafeKey,
356
- z.array(z.union([zSafeText, UiNodeSchema])).max(UI_LIMITS.MAX_NODES)
357
- )
358
- .optional(),
359
- slotName: zSafeKey.optional(),
360
- children: z
361
- .array(z.union([zSafeText, UiNodeSchema]))
362
- .max(UI_LIMITS.MAX_NODES) // soft guard; hard guard below
363
- .optional(),
364
- })
365
- .strict()
366
- .superRefine((node, ctx) => {
367
- const isWidget = node.type === "widget";
368
- const isSlot = node.type === "slot";
369
- const isRepeat = node.type === "repeat";
370
-
371
- if (isWidget) {
372
- if (!node.widgetId) {
373
- ctx.addIssue({
374
- code: z.ZodIssueCode.custom,
375
- message: "widgetId is required for widget nodes",
376
- });
377
- }
378
- if (node.className || node.props || node.events || node.bind) {
379
- ctx.addIssue({
380
- code: z.ZodIssueCode.custom,
381
- message:
382
- "widget nodes cannot use className/props/events/bind; use widgetProps and slots",
383
- });
384
- }
385
- if (node.children) {
386
- ctx.addIssue({
387
- code: z.ZodIssueCode.custom,
388
- message: "widget nodes must use slots instead of children",
389
- });
390
- }
391
- if (node.slotName) {
392
- ctx.addIssue({
393
- code: z.ZodIssueCode.custom,
394
- message: "widget nodes cannot define slotName",
395
- });
396
- }
397
- } else if (isSlot) {
398
- if (!node.slotName) {
399
- ctx.addIssue({
400
- code: z.ZodIssueCode.custom,
401
- message: "slotName is required for slot nodes",
402
- });
403
- }
404
- if (
405
- node.className ||
406
- node.props ||
407
- node.events ||
408
- node.bind ||
409
- node.children ||
410
- node.widgetId ||
411
- node.widgetProps ||
412
- node.slots
413
- ) {
414
- ctx.addIssue({
415
- code: z.ZodIssueCode.custom,
416
- message: "slot nodes cannot include other node fields",
417
- });
418
- }
419
- } else if (isRepeat) {
420
- if (!node.items || !node.as) {
421
- ctx.addIssue({
422
- code: z.ZodIssueCode.custom,
423
- message: "repeat nodes require items and as",
424
- });
425
- }
426
- if (node.className || node.props || node.events || node.bind) {
427
- ctx.addIssue({
428
- code: z.ZodIssueCode.custom,
429
- message: "repeat nodes cannot use className/props/events/bind",
430
- });
431
- }
432
- if (node.widgetId || node.widgetProps || node.slots || node.slotName) {
433
- ctx.addIssue({
434
- code: z.ZodIssueCode.custom,
435
- message: "repeat nodes cannot include widget/slot fields",
436
- });
437
- }
438
- } else {
439
- if (
440
- node.widgetId ||
441
- node.widgetProps ||
442
- node.slots ||
443
- node.slotName ||
444
- node.items ||
445
- node.as ||
446
- node.indexAs
447
- ) {
448
- ctx.addIssue({
449
- code: z.ZodIssueCode.custom,
450
- message:
451
- "reserved widget/slot/repeat fields are not allowed on UI nodes",
452
- });
453
- }
454
- }
455
- })
456
- );
457
-
458
- export type UiNode = z.infer<typeof UiNodeSchema>;
459
-
460
- // ------------------ Messages ------------------
461
-
462
- export const UiTemplateSchema = z
463
- .object({
464
- schema: z.literal("ui.v1"),
465
- root: UiNodeSchema,
466
- })
467
- .strict();
468
-
469
- export type UiTemplate = z.infer<typeof UiTemplateSchema>;
470
-
471
- const WidgetPropSchema = z
472
- .object({
473
- type: z.enum(["string", "number", "boolean", "json"]),
474
- required: z.boolean().optional(),
475
- default: z.unknown().optional(),
476
- })
477
- .strict();
478
-
479
- export const WidgetPolicySchema = z
480
- .object({
481
- allowedTags: z.array(z.string().min(1).max(50)).optional(),
482
- allowedProps: z.array(zSafeKey).optional(),
483
- allowedActions: z.array(UiActionTypeSchema).optional(),
484
- maxNodes: z.number().int().min(1).max(UI_LIMITS.MAX_NODES).optional(),
485
- maxDepth: z.number().int().min(1).max(UI_LIMITS.MAX_DEPTH).optional(),
486
- })
487
- .strict()
488
- .optional();
489
-
490
- export const WidgetDefinitionSchema = z
491
- .object({
492
- schema: z.literal("widget.v1"),
493
- widgetId: zSafeId,
494
- version: z.string().min(1).max(50),
495
- template: UiTemplateSchema,
496
- props: z.record(zSafeKey, WidgetPropSchema).optional(),
497
- slots: z
498
- .record(zSafeKey, z.object({ required: z.boolean().optional() }).strict())
499
- .optional(),
500
- policy: WidgetPolicySchema,
501
- })
502
- .strict();
503
-
504
- export type WidgetDefinition = z.infer<typeof WidgetDefinitionSchema>;
505
-
506
- export const FlowOutputSchema = z.discriminatedUnion("kind", [
507
- z.object({ kind: z.literal("text"), text: zSafeText }),
508
- z.object({ kind: z.literal("markdown"), markdown: zSafeText }),
509
- z.object({
510
- kind: z.literal("ui"),
511
- templateId: z.string().min(1).max(200),
512
- data: z.record(z.string(), z.unknown()).optional(),
513
- }),
514
- ]);
515
-
516
- export type FlowOutput = z.infer<typeof FlowOutputSchema>;
517
-
518
- export const WsClientEventSchema = z.discriminatedUnion("kind", [
519
- z.object({
520
- kind: z.literal("ui_event"),
521
- name: z.string().min(1).max(200),
522
- payload: z.record(z.string(), z.unknown()).optional(),
523
- }),
524
- ]);
525
-
526
- export type WsClientEvent = z.infer<typeof WsClientEventSchema>;
527
-
528
- export const WsServerMessageSchema = z.object({
529
- kind: z.literal("flow_output"),
530
- output: FlowOutputSchema,
531
- });
532
-
533
- export type WsServerMessage = z.infer<typeof WsServerMessageSchema>;
534
-
535
- // ------------------ Hard guard helpers ------------------
536
-
537
- export function countNodes(root: UiNode): { nodes: number; depth: number } {
538
- let nodes = 0;
539
- let maxDepth = 0;
540
-
541
- function walk(node: UiNode, depth: number) {
542
- nodes += 1;
543
- if (depth > maxDepth) maxDepth = depth;
544
-
545
- const children = node.children ?? [];
546
- for (const c of children) {
547
- if (typeof c === "string") continue;
548
- walk(c, depth + 1);
549
- }
550
-
551
- const slots = node.slots ? Object.values(node.slots) : [];
552
- for (const slotNodes of slots as any) {
553
- for (const c of slotNodes) {
554
- if (typeof c === "string") continue;
555
- walk(c, depth + 1);
556
- }
557
- }
558
- }
559
-
560
- walk(root, 1);
561
- return { nodes, depth: maxDepth };
562
- }
563
-
564
- export function assertWithinLimits(template: UiTemplate): void {
565
- const { nodes, depth } = countNodes(template.root);
566
- if (nodes > UI_LIMITS.MAX_NODES) {
567
- throw new Error(
568
- `UI template too large: nodes=${nodes} > ${UI_LIMITS.MAX_NODES}`
569
- );
570
- }
571
- if (depth > UI_LIMITS.MAX_DEPTH) {
572
- throw new Error(
573
- `UI template too deep: depth=${depth} > ${UI_LIMITS.MAX_DEPTH}`
574
- );
575
- }
576
- }
package/tsconfig.json DELETED
@@ -1,14 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "ESNext",
5
- "declaration": true,
6
- "declarationMap": true,
7
- "outDir": "dist",
8
- "rootDir": "src",
9
- "moduleResolution": "Bundler",
10
- "strict": true,
11
- "skipLibCheck": true
12
- },
13
- "include": ["src"]
14
- }