diff --git a/apps/builder/app/builder/features/settings-panel/props-section/props-section.stories.tsx b/apps/builder/app/builder/features/settings-panel/props-section/props-section.stories.tsx index 0066bcf00e8b..5a5873a02ddf 100644 --- a/apps/builder/app/builder/features/settings-panel/props-section/props-section.stories.tsx +++ b/apps/builder/app/builder/features/settings-panel/props-section/props-section.stories.tsx @@ -1,6 +1,5 @@ import { useState } from "react"; -import type { Instance, Prop, Asset } from "@webstudio-is/sdk"; -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { Instance, Prop, Asset, PropMeta } from "@webstudio-is/sdk"; import { textVariants } from "@webstudio-is/design-system"; import { PropsSection } from "./props-section"; import { usePropsLogic } from "./use-props-logic"; diff --git a/apps/builder/app/builder/features/settings-panel/props-section/use-props-logic.ts b/apps/builder/app/builder/features/settings-panel/props-section/use-props-logic.ts index 4d8d9fae5e5a..04bae02862a9 100644 --- a/apps/builder/app/builder/features/settings-panel/props-section/use-props-logic.ts +++ b/apps/builder/app/builder/features/settings-panel/props-section/use-props-logic.ts @@ -1,8 +1,7 @@ import { useState } from "react"; import { nanoid } from "nanoid"; -import type { Instance, Prop } from "@webstudio-is/sdk"; +import type { Instance, Prop, PropMeta } from "@webstudio-is/sdk"; import { - type PropMeta, type WsComponentPropsMeta, showAttribute, } from "@webstudio-is/react-sdk"; diff --git a/apps/builder/app/builder/features/settings-panel/shared.tsx b/apps/builder/app/builder/features/settings-panel/shared.tsx index acaca5f6d29b..c4e9c303a509 100644 --- a/apps/builder/app/builder/features/settings-panel/shared.tsx +++ b/apps/builder/app/builder/features/settings-panel/shared.tsx @@ -6,8 +6,7 @@ import { useEffect, } from "react"; import equal from "fast-deep-equal"; -import type { PropMeta } from "@webstudio-is/react-sdk"; -import type { Prop, Asset } from "@webstudio-is/sdk"; +import type { Prop, Asset, PropMeta } from "@webstudio-is/sdk"; import { SubtractIcon } from "@webstudio-is/icons"; import { SmallIconButton, diff --git a/packages/generate-arg-types/package.json b/packages/generate-arg-types/package.json index 9e7f4ba3b019..647ffe3cc165 100644 --- a/packages/generate-arg-types/package.json +++ b/packages/generate-arg-types/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@webstudio-is/html-data": "workspace:*", - "@webstudio-is/react-sdk": "workspace:*", + "@webstudio-is/sdk": "workspace:*", "fast-glob": "^3.2.12", "react-docgen-typescript": "^2.2.2", "zod": "^3.21.4" diff --git a/packages/generate-arg-types/src/arg-types.ts b/packages/generate-arg-types/src/arg-types.ts index ea040ac109b3..aca43d8b3276 100644 --- a/packages/generate-arg-types/src/arg-types.ts +++ b/packages/generate-arg-types/src/arg-types.ts @@ -1,5 +1,5 @@ import type { PropItem } from "react-docgen-typescript"; -import { PropMeta } from "@webstudio-is/react-sdk"; +import { PropMeta } from "@webstudio-is/sdk"; export type FilterPredicate = (prop: PropItem) => boolean; diff --git a/packages/generate-arg-types/src/cli.ts b/packages/generate-arg-types/src/cli.ts index 3fa4997d1b4c..dfc401aefbea 100755 --- a/packages/generate-arg-types/src/cli.ts +++ b/packages/generate-arg-types/src/cli.ts @@ -101,7 +101,7 @@ type CustomDescriptionsType = { continue; } - let fileContent = `import type { PropMeta } from "@webstudio-is/react-sdk";\n`; + let fileContent = `import type { PropMeta } from "@webstudio-is/sdk";\n`; if (componentDocs.length === 1) { const argTypes = propsToArgTypes( diff --git a/packages/html-data/package.json b/packages/html-data/package.json index 4bee3bc1361a..bcbf2003f3b7 100644 --- a/packages/html-data/package.json +++ b/packages/html-data/package.json @@ -5,17 +5,26 @@ "author": "Webstudio ", "homepage": "https://webstudio.is", "type": "module", + "bin": { + "generate-html-props-meta": "./src/generate-html-props-meta.ts" + }, "scripts": { "typecheck": "tsc", "checks": "pnpm typecheck", "dev": "pnpm build --watch", "build": "rm -rf lib && esbuild 'src/**/*.ts' 'src/**/*.tsx' --outdir=lib", + "build:attributes": "tsx ./src/find-html-attributes.ts && prettier --write src/__generated__/html-attributes.ts", "dts": "tsc --project tsconfig.dts.json" }, + "dependencies": { + "@webstudio-is/sdk": "workspace:*", + "html-tags": "^3.3.1", + "parse5": "^7.1.2" + }, "devDependencies": { + "@types/node": "^18.11.18", "@webstudio-is/tsconfig": "workspace:*" }, - "peerDependencies": {}, "exports": { "webstudio": "./src/index.ts", "types": "./lib/types/index.d.ts", @@ -27,6 +36,5 @@ ], "license": "AGPL-3.0-or-later", "private": true, - "sideEffects": false, - "dependencies": {} + "sideEffects": false } diff --git a/packages/html-data/src/__generated__/html-attributes.ts b/packages/html-data/src/__generated__/html-attributes.ts new file mode 100644 index 000000000000..b37db1a06ecb --- /dev/null +++ b/packages/html-data/src/__generated__/html-attributes.ts @@ -0,0 +1,1500 @@ +import type { AttributesByTag } from "../types"; +export const htmlAttributes: AttributesByTag = { + th: [ + { name: "abbr", type: "string" }, + { + name: "colspan", + type: "number", + description: + "The colspan attribute defines the number of columns a cell should span.", + }, + { + name: "headers", + type: "string", + description: "IDs of the elements which applies to this element.", + }, + { + name: "rowspan", + type: "number", + description: "Defines the number of rows a table cell should span over.", + }, + { + name: "scope", + type: "enum", + values: ["row", "col", "rowgroup", "colgroup"], + description: + "Defines the cells that the header test (defined in theth element) relates to.", + }, + ], + input: [ + { + name: "accept", + type: "string", + description: "List of types the server accepts, typically a file type.", + }, + { + name: "alt", + type: "string", + description: + "Text description of the image, which is very important for accessibility and search engine optimization. Screen readers read this description to users so they know what the image means. Alt text is also displayed on the page if the image can't be loaded for some reason.", + }, + { + name: "autocomplete", + type: "string", + description: + "Indicates whether controls in this form can by default have their valuesautomatically completed by the browser.", + }, + { + name: "checked", + type: "boolean", + description: + "Indicates whether the element should be checked on page load.", + }, + { name: "dirname", type: "string" }, + { + name: "disabled", + type: "boolean", + description: "Indicates whether the user can interact with the element.", + }, + { + name: "form", + type: "string", + description: "Indicates the form that is the owner of the element.", + }, + { + name: "formaction", + type: "string", + description: + "Indicates the action of the element, overriding the action defined inthe form.", + }, + { + name: "formenctype", + type: "enum", + values: [ + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain", + ], + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute sets the encoding type to use during form submission. If this attribute is specified, it overrides theenctype attribute of the button\'s form owner.', + }, + { + name: "formmethod", + type: "enum", + values: ["GET", "POST", "dialog"], + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute sets the submission method to use during form submission (GET, POST, etc.). If this attribute is specified, it overrides the method attribute of the button\'s form owner.', + }, + { + name: "formnovalidate", + type: "boolean", + description: + 'If the button/input is a submit button (e.g. type="submit"), this boolean attribute specifies that the form is not to be validatedwhen it is submitted. If this attribute is specified, it overrides thenovalidate attribute of the button\'s form owner.', + }, + { + name: "formtarget", + type: "string", + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute specifies the browsing context (for example, tab, window, or inline frame) in which to display the response that is received aftersubmitting the form. If this attribute is specified, it overrides thetarget attribute of the button\'s form owner.', + }, + { + name: "height", + type: "number", + description: "Defines the image’s height in pixels.", + }, + { + name: "list", + type: "string", + description: + "Identifies a list of pre-defined options to suggest to the user.", + }, + { + name: "max", + type: "string", + description: "Indicates the maximum value allowed.", + }, + { + name: "maxlength", + type: "number", + description: + "Defines the maximum number of characters allowed in the element.", + }, + { + name: "min", + type: "string", + description: "Indicates the minimum value allowed.", + }, + { + name: "minlength", + type: "number", + description: + "Defines the minimum number of characters allowed in the element.", + }, + { + name: "multiple", + type: "boolean", + description: + "Indicates whether multiple values can be entered in an input of the type email or file.", + }, + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + { + name: "pattern", + type: "string", + description: + "Defines a regular expression which the element's value will be validated against.", + }, + { + name: "placeholder", + type: "string", + description: + "Provides a hint to the user of what can be entered in the field.", + }, + { name: "popovertarget", type: "string" }, + { + name: "popovertargetaction", + type: "enum", + values: ["toggle", "show", "hide"], + }, + { + name: "readonly", + type: "boolean", + description: "Indicates whether the element can be edited.", + }, + { + name: "required", + type: "boolean", + description: + "Indicates whether this form element must be filled before the form can be submitted.", + }, + { + name: "size", + type: "number", + description: + "Defines the width of the element (in pixels). If the element'stype attribute is text or password then it's the number of characters.", + }, + { + name: "src", + type: "string", + description: "The URL of the embeddable content.", + }, + { name: "step", type: "number" }, + { + name: "title", + type: "string", + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, + { + name: "type", + type: "string", + description: "Defines the type of the element.", + }, + { + name: "value", + type: "string", + description: + "Defines a default value which will be displayed in the element on pageload.", + }, + { + name: "width", + type: "number", + description: "Defines the image’s width in pixels.", + }, + ], + form: [ + { + name: "accept-charset", + type: "string", + description: "List of supported charsets.", + }, + { + name: "action", + type: "string", + description: + "The URI of a program that processes the information submitted via the form.", + }, + { + name: "autocomplete", + type: "enum", + values: ["on", "off"], + description: + "Indicates whether controls in this form can by default have their valuesautomatically completed by the browser.", + }, + { + name: "enctype", + type: "enum", + values: [ + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain", + ], + description: + "Defines the content type of the form data when themethod is POST.", + }, + { + name: "method", + type: "enum", + values: ["GET", "POST", "dialog"], + description: + "Defines which HTTP method to use when submitting the form. Can be GET (default) or POST.", + }, + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + { + name: "novalidate", + type: "boolean", + description: + "This attribute indicates that the form shouldn't be validated when submitted.", + }, + { + name: "target", + type: "string", + description: + "Specifies where to open the linked document (in the case of an element) or where to display the response received (in the case of a
element)", + }, + ], + "*": [ + { + name: "accesskey", + type: "string", + description: "Keyboard shortcut to activate or add focus to the element.", + }, + { + name: "autocapitalize", + type: "enum", + values: ["on", "off", "none", "sentences", "words", "characters"], + description: + "Sets whether input is automatically capitalized when entered by user.", + }, + { + name: "autofocus", + type: "boolean", + description: + "Indicates that an element should be focused on page load, or when its parent dialog is displayed.", + }, + { + name: "class", + type: "string", + description: + "Often used with CSS to style elements with common properties.", + }, + { + name: "contenteditable", + type: "enum", + values: ["true", "plaintext-only", "false"], + description: "Indicates whether the element's content is editable.", + }, + { + name: "dir", + type: "enum", + values: ["ltr", "rtl", "auto"], + description: + "Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)", + }, + { + name: "draggable", + type: "enum", + values: ["true", "false"], + description: "Defines whether the element can be dragged.", + }, + { + name: "enterkeyhint", + type: "enum", + values: ["enter", "done", "go", "next", "previous", "search", "send"], + description: + "The enterkeyhint specifies what action label (or icon) to present for the enter key onvirtual keyboards. The attribute can be used with form controls (such asthe value of textarea elements), or in elements in anediting host (e.g., using contenteditable attribute).", + }, + { + name: "hidden", + type: "enum", + values: ["until-found", "hidden"], + description: + "Prevents rendering of given element, while keeping child elements, e.g. script elements, active.", + }, + { + name: "id", + type: "string", + description: + "Often used with CSS to style a specific element. The value of this attribute must be unique.", + }, + { name: "inert", type: "boolean" }, + { + name: "inputmode", + type: "enum", + values: [ + "none", + "text", + "tel", + "email", + "url", + "numeric", + "decimal", + "search", + ], + description: + "Provides a hint as to the type of data that might be entered by the user while editing the element or its contents. The attribute can be used with form controls (such as the value oftextarea elements), or in elements in an editing host (e.g., using contenteditable attribute).", + }, + { name: "is", type: "string" }, + { name: "itemid", type: "string" }, + { name: "itemprop", type: "string" }, + { name: "itemref", type: "string" }, + { name: "itemscope", type: "boolean" }, + { name: "itemtype", type: "string" }, + { + name: "lang", + type: "string", + description: "Defines the language used in the element.", + }, + { name: "nonce", type: "string" }, + { name: "popover", type: "enum", values: ["auto", "manual"] }, + { + name: "slot", + type: "string", + description: "Assigns a slot in a shadow DOM shadow tree to an element.", + }, + { + name: "spellcheck", + type: "enum", + values: ["true", "false"], + description: + "Indicates whether spell checking is allowed for the element.", + }, + { + name: "style", + type: "string", + description: + "Defines CSS styles which will override styles previously set.", + }, + { + name: "tabindex", + type: "number", + description: + "Overrides the browser's default tab order and follows the one specified instead.", + }, + { + name: "title", + type: "string", + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, + { + name: "translate", + type: "enum", + values: ["yes", "no"], + description: + "Specify whether an element's attribute values and the values of its text node children are to be translated when the page is localized, or whether to leave them unchanged.", + }, + ], + iframe: [ + { + name: "allow", + type: "string", + description: "Specifies a feature-policy for the iframe.", + }, + { name: "allowfullscreen", type: "boolean" }, + { + name: "height", + type: "number", + description: "Defines the image’s height in pixels.", + }, + { + name: "loading", + type: "enum", + values: ["lazy", "eager"], + description: + "Determines whether the image will load as soon as possible (Eager), or when it scrolls into view (Lazy). Lazy loading is a great option for pages with many images because it can significantly reduce the time it takes for the page to load initially.", + }, + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + { + name: "referrerpolicy", + type: "string", + description: + "Specifies which referrer is sent when fetching the resource.", + }, + { + name: "sandbox", + type: "string", + description: + "Stops a document loaded in an iframe from using certain features (such as submitting forms or opening new windows).", + }, + { + name: "src", + type: "string", + description: "The URL of the embeddable content.", + }, + { name: "srcdoc", type: "string" }, + { + name: "width", + type: "number", + description: "Defines the image’s width in pixels.", + }, + ], + area: [ + { + name: "alt", + type: "string", + description: + "Text description of the image, which is very important for accessibility and search engine optimization. Screen readers read this description to users so they know what the image means. Alt text is also displayed on the page if the image can't be loaded for some reason.", + }, + { + name: "coords", + type: "number", + description: + "A set of values specifying the coordinates of the hot-spot region.", + }, + { + name: "download", + type: "string", + description: + "Indicates that the hyperlink is to be used for downloading a resource.", + }, + { + name: "href", + type: "string", + description: "The URL of a linked resource.", + }, + { + name: "ping", + type: "string", + description: + "The ping attribute specifies a space-separated list of URLs to be notified if a user follows the hyperlink.", + }, + { + name: "referrerpolicy", + type: "string", + description: + "Specifies which referrer is sent when fetching the resource.", + }, + { + name: "rel", + type: "string", + description: + "Specifies the relationship of the target object to the link object.", + }, + { + name: "shape", + type: "enum", + values: ["circle", "default", "poly", "rect"], + }, + { + name: "target", + type: "string", + description: + "Specifies where to open the linked document (in the case of an element) or where to display the response received (in the case of a element)", + }, + ], + img: [ + { + name: "alt", + type: "string", + description: + "Text description of the image, which is very important for accessibility and search engine optimization. Screen readers read this description to users so they know what the image means. Alt text is also displayed on the page if the image can't be loaded for some reason.", + }, + { + name: "crossorigin", + type: "enum", + values: ["anonymous", "use-credentials"], + description: "How the element handles cross-origin requests", + }, + { + name: "decoding", + type: "enum", + values: ["sync", "async", "auto"], + description: "Indicates the preferred method to decode the image.", + }, + { name: "fetchpriority", type: "enum", values: ["auto", "high", "low"] }, + { + name: "height", + type: "number", + description: "Defines the image’s height in pixels.", + }, + { + name: "ismap", + type: "boolean", + description: + "Indicates that the image is part of a server-side image map.", + }, + { + name: "loading", + type: "enum", + values: ["lazy", "eager"], + description: + "Determines whether the image will load as soon as possible (Eager), or when it scrolls into view (Lazy). Lazy loading is a great option for pages with many images because it can significantly reduce the time it takes for the page to load initially.", + }, + { + name: "referrerpolicy", + type: "string", + description: + "Specifies which referrer is sent when fetching the resource.", + }, + { name: "sizes", type: "string" }, + { + name: "src", + type: "string", + description: "The URL of the embeddable content.", + }, + { + name: "srcset", + type: "string", + description: "One or more responsive image candidates.", + }, + { name: "usemap", type: "string" }, + { + name: "width", + type: "number", + description: "Defines the image’s width in pixels.", + }, + ], + link: [ + { name: "as", type: "enum", values: [] }, + { name: "blocking", type: "string" }, + { + name: "color", + type: "string", + description: + "This attribute sets the text color using either a named color or a color specified in the hexadecimal #RRGGBB format. Note: This is a legacy attribute. Please use the CSS color property instead.", + }, + { + name: "crossorigin", + type: "enum", + values: ["anonymous", "use-credentials"], + description: "How the element handles cross-origin requests", + }, + { + name: "disabled", + type: "boolean", + description: "Indicates whether the user can interact with the element.", + }, + { name: "fetchpriority", type: "enum", values: ["auto", "high", "low"] }, + { + name: "href", + type: "string", + description: "The URL of a linked resource.", + }, + { + name: "hreflang", + type: "string", + description: "Specifies the language of the linked resource.", + }, + { name: "imagesizes", type: "string" }, + { name: "imagesrcset", type: "string" }, + { + name: "integrity", + type: "string", + description: + "Specifies a Subresource Integrity value that allows browsers to verify what they fetch.", + }, + { + name: "media", + type: "string", + description: + "Specifies a hint of the media for which the linked resource was designed.", + }, + { + name: "referrerpolicy", + type: "string", + description: + "Specifies which referrer is sent when fetching the resource.", + }, + { + name: "rel", + type: "string", + description: + "Specifies the relationship of the target object to the link object.", + }, + { name: "sizes", type: "string" }, + { + name: "title", + type: "string", + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, + { + name: "title", + type: "string", + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, + { + name: "type", + type: "string", + description: "Defines the type of the element.", + }, + ], + script: [ + { + name: "async", + type: "boolean", + description: "Executes the script asynchronously.", + }, + { name: "blocking", type: "string" }, + { + name: "crossorigin", + type: "enum", + values: ["anonymous", "use-credentials"], + description: "How the element handles cross-origin requests", + }, + { + name: "defer", + type: "boolean", + description: + "Indicates that the script should be executed after the page has beenparsed.", + }, + { name: "fetchpriority", type: "enum", values: ["auto", "high", "low"] }, + { + name: "integrity", + type: "string", + description: + "Specifies a Subresource Integrity value that allows browsers to verify what they fetch.", + }, + { name: "nomodule", type: "boolean" }, + { + name: "referrerpolicy", + type: "string", + description: + "Specifies which referrer is sent when fetching the resource.", + }, + { + name: "src", + type: "string", + description: "The URL of the embeddable content.", + }, + { + name: "type", + type: "enum", + values: ["module"], + description: "Defines the type of the element.", + }, + ], + select: [ + { + name: "autocomplete", + type: "string", + description: + "Indicates whether controls in this form can by default have their valuesautomatically completed by the browser.", + }, + { + name: "disabled", + type: "boolean", + description: "Indicates whether the user can interact with the element.", + }, + { + name: "form", + type: "string", + description: "Indicates the form that is the owner of the element.", + }, + { + name: "multiple", + type: "boolean", + description: + "Indicates whether multiple values can be entered in an input of the type email or file.", + }, + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + { + name: "required", + type: "boolean", + description: + "Indicates whether this form element must be filled before the form can be submitted.", + }, + { + name: "size", + type: "number", + description: + "Defines the width of the element (in pixels). If the element'stype attribute is text or password then it's the number of characters.", + }, + ], + textarea: [ + { + name: "autocomplete", + type: "string", + description: + "Indicates whether controls in this form can by default have their valuesautomatically completed by the browser.", + }, + { + name: "cols", + type: "number", + description: "Defines the number of columns in a textarea.", + }, + { name: "dirname", type: "string" }, + { + name: "disabled", + type: "boolean", + description: "Indicates whether the user can interact with the element.", + }, + { + name: "form", + type: "string", + description: "Indicates the form that is the owner of the element.", + }, + { + name: "maxlength", + type: "number", + description: + "Defines the maximum number of characters allowed in the element.", + }, + { + name: "minlength", + type: "number", + description: + "Defines the minimum number of characters allowed in the element.", + }, + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + { + name: "placeholder", + type: "string", + description: + "Provides a hint to the user of what can be entered in the field.", + }, + { + name: "readonly", + type: "boolean", + description: "Indicates whether the element can be edited.", + }, + { + name: "required", + type: "boolean", + description: + "Indicates whether this form element must be filled before the form can be submitted.", + }, + { + name: "rows", + type: "number", + description: "Defines the number of rows in a text area.", + }, + { + name: "wrap", + type: "enum", + values: ["soft", "hard"], + description: "Indicates whether the text should be wrapped.", + }, + ], + audio: [ + { + name: "autoplay", + type: "boolean", + description: "The audio or video should play as soon as possible.", + }, + { + name: "controls", + type: "boolean", + description: + "Indicates whether the browser should show playback controls to the user.", + }, + { + name: "crossorigin", + type: "enum", + values: ["anonymous", "use-credentials"], + description: "How the element handles cross-origin requests", + }, + { + name: "loop", + type: "boolean", + description: + "Indicates whether the media should start playing from the start when it's finished.", + }, + { + name: "muted", + type: "boolean", + description: + "Indicates whether the audio will be initially silenced on page load.", + }, + { + name: "preload", + type: "enum", + values: ["none", "metadata", "auto"], + description: + "Indicates whether the whole resource, parts of it or nothing should be preloaded.", + }, + { + name: "src", + type: "string", + description: "The URL of the embeddable content.", + }, + ], + video: [ + { + name: "autoplay", + type: "boolean", + description: "The audio or video should play as soon as possible.", + }, + { + name: "controls", + type: "boolean", + description: + "Indicates whether the browser should show playback controls to the user.", + }, + { + name: "crossorigin", + type: "enum", + values: ["anonymous", "use-credentials"], + description: "How the element handles cross-origin requests", + }, + { + name: "height", + type: "number", + description: "Defines the image’s height in pixels.", + }, + { + name: "loop", + type: "boolean", + description: + "Indicates whether the media should start playing from the start when it's finished.", + }, + { + name: "muted", + type: "boolean", + description: + "Indicates whether the audio will be initially silenced on page load.", + }, + { + name: "playsinline", + type: "boolean", + description: + 'A Boolean attribute indicating that the video is to be played "inline"; that is, within the element\'s playback area. Note that the absence of this attribute does not imply that the video will always be played in fullscreen.', + }, + { + name: "poster", + type: "string", + description: + "A URL indicating a poster frame to show until the user plays or seeks.", + }, + { + name: "preload", + type: "enum", + values: ["none", "metadata", "auto"], + description: + "Indicates whether the whole resource, parts of it or nothing should be preloaded.", + }, + { + name: "src", + type: "string", + description: "The URL of the embeddable content.", + }, + { + name: "width", + type: "number", + description: "Defines the image’s width in pixels.", + }, + ], + style: [ + { name: "blocking", type: "string" }, + { + name: "media", + type: "string", + description: + "Specifies a hint of the media for which the linked resource was designed.", + }, + { + name: "title", + type: "string", + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, + ], + meta: [ + { + name: "charset", + type: "string", + description: "Declares the character encoding of the page or script.", + }, + { + name: "content", + type: "string", + description: + "A value associated with http-equiv orname depending on the context.", + }, + { + name: "http-equiv", + type: "enum", + values: [ + "content-type", + "default-style", + "refresh", + "x-ua-compatible", + "content-security-policy", + ], + description: "Defines a pragma directive.", + }, + { + name: "media", + type: "string", + description: + "Specifies a hint of the media for which the linked resource was designed.", + }, + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + ], + blockquote: [ + { + name: "cite", + type: "string", + description: + "Contains a URI which points to the source of the quote or change.", + }, + ], + del: [ + { + name: "cite", + type: "string", + description: + "Contains a URI which points to the source of the quote or change.", + }, + { + name: "datetime", + type: "string", + description: "Indicates the date and time associated with the element.", + }, + ], + ins: [ + { + name: "cite", + type: "string", + description: + "Contains a URI which points to the source of the quote or change.", + }, + { + name: "datetime", + type: "string", + description: "Indicates the date and time associated with the element.", + }, + ], + q: [ + { + name: "cite", + type: "string", + description: + "Contains a URI which points to the source of the quote or change.", + }, + ], + td: [ + { + name: "colspan", + type: "number", + description: + "The colspan attribute defines the number of columns a cell should span.", + }, + { + name: "headers", + type: "string", + description: "IDs of the elements which applies to this element.", + }, + { + name: "rowspan", + type: "number", + description: "Defines the number of rows a table cell should span over.", + }, + ], + object: [ + { + name: "data", + type: "string", + description: "Specifies the URL of the resource.", + }, + { + name: "form", + type: "string", + description: "Indicates the form that is the owner of the element.", + }, + { + name: "height", + type: "number", + description: "Defines the image’s height in pixels.", + }, + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + { + name: "type", + type: "string", + description: "Defines the type of the element.", + }, + { + name: "width", + type: "number", + description: "Defines the image’s width in pixels.", + }, + ], + time: [ + { + name: "datetime", + type: "number", + description: "Indicates the date and time associated with the element.", + }, + ], + track: [ + { + name: "default", + type: "boolean", + description: + "Indicates that the track should be enabled unless the user's preferencesindicate something different.", + }, + { + name: "kind", + type: "enum", + values: ["subtitles", "captions", "descriptions", "chapters", "metadata"], + description: "Specifies the kind of text track.", + }, + { + name: "label", + type: "string", + description: "Specifies a user-readable title of the element.", + }, + { + name: "src", + type: "string", + description: "The URL of the embeddable content.", + }, + { name: "srclang", type: "string" }, + ], + bdo: [ + { + name: "dir", + type: "enum", + values: ["ltr", "rtl"], + description: + "Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)", + }, + ], + button: [ + { + name: "disabled", + type: "boolean", + description: "Indicates whether the user can interact with the element.", + }, + { + name: "form", + type: "string", + description: "Indicates the form that is the owner of the element.", + }, + { + name: "formaction", + type: "string", + description: + "Indicates the action of the element, overriding the action defined inthe form.", + }, + { + name: "formenctype", + type: "enum", + values: [ + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain", + ], + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute sets the encoding type to use during form submission. If this attribute is specified, it overrides theenctype attribute of the button\'s form owner.', + }, + { + name: "formmethod", + type: "enum", + values: ["GET", "POST", "dialog"], + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute sets the submission method to use during form submission (GET, POST, etc.). If this attribute is specified, it overrides the method attribute of the button\'s form owner.', + }, + { + name: "formnovalidate", + type: "boolean", + description: + 'If the button/input is a submit button (e.g. type="submit"), this boolean attribute specifies that the form is not to be validatedwhen it is submitted. If this attribute is specified, it overrides thenovalidate attribute of the button\'s form owner.', + }, + { + name: "formtarget", + type: "string", + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute specifies the browsing context (for example, tab, window, or inline frame) in which to display the response that is received aftersubmitting the form. If this attribute is specified, it overrides thetarget attribute of the button\'s form owner.', + }, + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + { name: "popovertarget", type: "string" }, + { + name: "popovertargetaction", + type: "enum", + values: ["toggle", "show", "hide"], + }, + { + name: "type", + type: "enum", + values: ["submit", "reset", "button"], + description: "Defines the type of the element.", + }, + { + name: "value", + type: "string", + description: + "Defines a default value which will be displayed in the element on pageload.", + }, + ], + optgroup: [ + { + name: "disabled", + type: "boolean", + description: "Indicates whether the user can interact with the element.", + }, + { + name: "label", + type: "string", + description: "Specifies a user-readable title of the element.", + }, + ], + option: [ + { + name: "disabled", + type: "boolean", + description: "Indicates whether the user can interact with the element.", + }, + { + name: "label", + type: "string", + description: "Specifies a user-readable title of the element.", + }, + { + name: "selected", + type: "boolean", + description: "Defines a value which will be selected on page load.", + }, + { + name: "value", + type: "string", + description: + "Defines a default value which will be displayed in the element on pageload.", + }, + ], + fieldset: [ + { + name: "disabled", + type: "boolean", + description: "Indicates whether the user can interact with the element.", + }, + { + name: "form", + type: "string", + description: "Indicates the form that is the owner of the element.", + }, + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + ], + a: [ + { + name: "download", + type: "string", + description: + "Indicates that the hyperlink is to be used for downloading a resource.", + }, + { + name: "href", + type: "string", + description: "The URL of a linked resource.", + }, + { + name: "hreflang", + type: "string", + description: "Specifies the language of the linked resource.", + }, + { + name: "ping", + type: "string", + description: + "The ping attribute specifies a space-separated list of URLs to be notified if a user follows the hyperlink.", + }, + { + name: "referrerpolicy", + type: "string", + description: + "Specifies which referrer is sent when fetching the resource.", + }, + { + name: "rel", + type: "string", + description: + "Specifies the relationship of the target object to the link object.", + }, + { + name: "target", + type: "string", + description: + "Specifies where to open the linked document (in the case of an element) or where to display the response received (in the case of a element)", + }, + { + name: "type", + type: "string", + description: "Defines the type of the element.", + }, + ], + label: [ + { + name: "for", + type: "string", + description: + "Associates this Label with an Input. The value of the “For” attribute should match the ID attribute of the corresponding Input element", + }, + ], + output: [ + { + name: "for", + type: "string", + description: + "Associates this Label with an Input. The value of the “For” attribute should match the ID attribute of the corresponding Input element", + }, + { + name: "form", + type: "string", + description: "Indicates the form that is the owner of the element.", + }, + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + ], + canvas: [ + { + name: "height", + type: "number", + description: "Defines the image’s height in pixels.", + }, + { + name: "width", + type: "number", + description: "Defines the image’s width in pixels.", + }, + ], + embed: [ + { + name: "height", + type: "number", + description: "Defines the image’s height in pixels.", + }, + { + name: "src", + type: "string", + description: "The URL of the embeddable content.", + }, + { + name: "type", + type: "string", + description: "Defines the type of the element.", + }, + { + name: "width", + type: "number", + description: "Defines the image’s width in pixels.", + }, + ], + source: [ + { + name: "height", + type: "number", + description: "Defines the image’s height in pixels.", + }, + { + name: "media", + type: "string", + description: + "Specifies a hint of the media for which the linked resource was designed.", + }, + { name: "sizes", type: "string" }, + { + name: "src", + type: "string", + description: "The URL of the embeddable content.", + }, + { + name: "srcset", + type: "string", + description: "One or more responsive image candidates.", + }, + { + name: "type", + type: "string", + description: "Defines the type of the element.", + }, + { + name: "width", + type: "number", + description: "Defines the image’s width in pixels.", + }, + ], + meter: [ + { + name: "high", + type: "number", + description: "Indicates the lower bound of the upper range.", + }, + { + name: "low", + type: "number", + description: "Indicates the upper bound of the lower range.", + }, + { + name: "max", + type: "number", + description: "Indicates the maximum value allowed.", + }, + { + name: "min", + type: "number", + description: "Indicates the minimum value allowed.", + }, + { + name: "optimum", + type: "number", + description: "Indicates the optimal numeric value.", + }, + { + name: "value", + type: "number", + description: + "Defines a default value which will be displayed in the element on pageload.", + }, + ], + base: [ + { + name: "href", + type: "string", + description: "The URL of a linked resource.", + }, + { + name: "target", + type: "string", + description: + "Specifies where to open the linked document (in the case of an element) or where to display the response received (in the case of a element)", + }, + ], + progress: [ + { + name: "max", + type: "number", + description: "Indicates the maximum value allowed.", + }, + { + name: "value", + type: "number", + description: + "Defines a default value which will be displayed in the element on pageload.", + }, + ], + map: [ + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + ], + slot: [ + { + name: "name", + type: "string", + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + ], + details: [ + { + name: "open", + type: "boolean", + description: + "Indicates whether the contents are currently visible (in the case of a
element) or whether the dialog is active and can be interacted with (in the case of a element).", + }, + ], + dialog: [ + { + name: "open", + type: "boolean", + description: + "Indicates whether the contents are currently visible (in the case of a
element) or whether the dialog is active and can be interacted with (in the case of a element).", + }, + ], + ol: [ + { + name: "reversed", + type: "boolean", + description: + "Indicates whether the list should be displayed in a descending order instead of an ascending order.", + }, + { + name: "start", + type: "number", + description: "Defines the first number if other than 1.", + }, + { + name: "type", + type: "enum", + values: ["1", "a", "A", "i", "I"], + description: "Defines the type of the element.", + }, + ], + col: [{ name: "span", type: "number" }], + colgroup: [{ name: "span", type: "number" }], + abbr: [ + { + name: "title", + type: "string", + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, + ], + dfn: [ + { + name: "title", + type: "string", + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, + ], + data: [ + { + name: "value", + type: "string", + description: + "Defines a default value which will be displayed in the element on pageload.", + }, + ], + li: [ + { + name: "value", + type: "number", + description: + "Defines a default value which will be displayed in the element on pageload.", + }, + ], +}; diff --git a/packages/html-data/src/find-html-attributes.ts b/packages/html-data/src/find-html-attributes.ts new file mode 100644 index 000000000000..0f6e00a70538 --- /dev/null +++ b/packages/html-data/src/find-html-attributes.ts @@ -0,0 +1,119 @@ +import { writeFile, mkdir } from "node:fs/promises"; +import { Parser, defaultTreeAdapter } from "parse5"; +import type { Attribute, AttributesByTag } from "./types"; +import { htmlPropsDescriptions } from "./descriptions"; + +// scrub attributes data from https://html.spec.whatwg.org/multipage/indices.html#attributes-3 + +const response = await fetch( + "https://html.spec.whatwg.org/multipage/indices.html" +); +const text = await response.text(); +const document = Parser.parse(text, { treeAdapter: defaultTreeAdapter }); + +type ChildNode = (typeof document.childNodes)[0]; +type Node = typeof document | ChildNode; +type NodeWithChildren = Extract; + +const findTags = ( + node: undefined | Node, + tagName: string, + result: NodeWithChildren[] = [] +): NodeWithChildren[] => { + if (node && "childNodes" in node) { + if ("tagName" in node && node.tagName === tagName) { + result.push(node); + } + for (const child of node.childNodes) { + findTags(child, tagName, result); + } + } + return result; +}; + +const getAttr = (node: NodeWithChildren, name: string) => { + return node.attrs.find((attr) => attr.name === name); +}; + +const getTextContent = (node: ChildNode) => { + if ("value" in node) { + return node.value; + } + let result = ""; + if ("childNodes" in node) { + for (const child of node.childNodes) { + result += getTextContent(child); + } + } + return result; +}; + +const table = findTags(document, "table").find( + (table) => getAttr(table, "id")?.value === "attributes-1" +); +const [tbody] = findTags(table, "tbody"); +const rows = findTags(tbody, "tr"); + +const attributesByTag: AttributesByTag = {}; + +for (const tr of rows) { + const [nameColumn] = findTags(tr, "th"); + const [elementsColumn, _descriptionColumn, valueColumn] = findTags(tr, "td"); + const name = getTextContent(nameColumn).trim(); + const elements = getTextContent(elementsColumn) + .trim() + .split(/\s*;\s*/) + .map((element) => { + if (element === "HTML elements") { + return "*"; + } + if ( + element === "source (in picture)" || + element === "source (in video or audio)" + ) { + return "source"; + } + return element; + }) + .filter((element) => element !== "form-associated custom elements"); + const value = getTextContent(valueColumn) + .trim() + .split(/\s*;\s*/); + + let attribute: Attribute; + if (value.length === 1) { + if (value[0] === "Text" || value[0] === "Text*") { + attribute = { name, type: "string" }; + } else if (value[0] === "Boolean attribute") { + attribute = { name, type: "boolean" }; + } else if (value[0].includes("number") || value[0].includes("integer")) { + attribute = { name, type: "number" }; + } else { + attribute = { name, type: "string" }; + } + } else { + const values: string[] = []; + for (const item of value) { + if (item.startsWith('"') && item.endsWith('"')) { + values.push(item.slice(1, -1)); + } + // some values are not specific + } + attribute = { name, type: "enum", values }; + } + attribute.description = + htmlPropsDescriptions[name as keyof typeof htmlPropsDescriptions]; + for (const element of elements) { + const attributes = attributesByTag[element] ?? []; + attributesByTag[element] = attributes; + attributes.push(attribute); + } +} + +const json = JSON.stringify(attributesByTag); +const content = ` +import type { AttributesByTag } from "../types" +export const htmlAttributes: AttributesByTag = ${json} +`; +await mkdir("./src/__generated__", { recursive: true }); +await writeFile("./src/__generated__/html-attributes.ts", content); diff --git a/packages/html-data/src/generate-html-props-meta.ts b/packages/html-data/src/generate-html-props-meta.ts new file mode 100755 index 000000000000..00624e1c69ad --- /dev/null +++ b/packages/html-data/src/generate-html-props-meta.ts @@ -0,0 +1,95 @@ +#!/usr/bin/env tsx + +import { parseArgs } from "node:util"; +import { argv, cwd } from "node:process"; +import { mkdir, writeFile } from "node:fs/promises"; +import { dirname, join } from "node:path"; +import htmlTags from "html-tags"; +import { htmlAttributes } from "./__generated__/html-attributes"; +import type { Attribute } from "./types"; +import type { PropMeta } from "@webstudio-is/sdk"; +import { domAttributesToReact } from "."; + +const { positionals, values } = parseArgs({ + args: argv.slice(2), + allowPositionals: true, + options: { + convertName: { + type: "string", + }, + }, +}); + +const allowedConvertName = ["react"]; + +if ( + values.convertName === undefined || + allowedConvertName.includes(values.convertName) === false +) { + throw Error("Invalid or missing --convertName"); +} + +const [generatedPath] = positionals; + +const toPropMeta = (attribute: Attribute): PropMeta => { + const required = false; + const { description } = attribute; + if (attribute.type === "string") { + return { type: "string", control: "text", required, description }; + } + if (attribute.type === "number") { + return { type: "number", control: "number", required, description }; + } + if (attribute.type === "boolean") { + return { type: "boolean", control: "boolean", required, description }; + } + if (attribute.type === "enum") { + return { + type: "string", + control: attribute.values.length <= 3 ? "radio" : "select", + required, + options: attribute.values, + description, + }; + } + attribute satisfies never; + throw Error("never happens"); +}; + +const toPropsMeta = (attributes: Attribute[]) => { + const propsMeta: Record = {}; + for (const attribute of attributes) { + let name = attribute.name; + if (values.convertName === "react") { + name = + domAttributesToReact[name as keyof typeof domAttributesToReact] ?? name; + } + propsMeta[name] = toPropMeta(attribute); + } + return propsMeta; +}; + +const globalPropsMeta = toPropsMeta(htmlAttributes["*"]); +let content = ` +import type { PropMeta } from '@webstudio-is/sdk' + +const globals: Record = ${JSON.stringify(globalPropsMeta)} + +`; +for (const tag of htmlTags) { + if (htmlAttributes[tag]) { + const json = JSON.stringify(toPropsMeta(htmlAttributes[tag])); + content += `export const ${tag} = {...globals,${json.slice(1)}\n\n`; + continue; + } + if (tag === "var") { + content += `const _${tag} = globals\n`; + content += `export { _var as var }\n\n`; + continue; + } + content += `export const ${tag} = globals\n\n`; +} + +const path = join(cwd(), generatedPath); +await mkdir(dirname(path), { recursive: true }); +await writeFile(path, content); diff --git a/packages/html-data/src/types.ts b/packages/html-data/src/types.ts new file mode 100644 index 000000000000..39cdf59ed0e3 --- /dev/null +++ b/packages/html-data/src/types.ts @@ -0,0 +1,7 @@ +export type Attribute = + | { name: string; description?: string; type: "boolean" } + | { name: string; description?: string; type: "string" } + | { name: string; description?: string; type: "number" } + | { name: string; description?: string; type: "enum"; values: string[] }; + +export type AttributesByTag = Record; diff --git a/packages/react-sdk/package.json b/packages/react-sdk/package.json index 845d833edb13..6e3f88858249 100644 --- a/packages/react-sdk/package.json +++ b/packages/react-sdk/package.json @@ -8,6 +8,7 @@ "scripts": { "dev": "rm -rf lib && esbuild 'src/**/*.ts' 'src/**/*.tsx' --outdir=lib --watch", "build": "rm -rf lib && esbuild src/index.ts ./src/css/normalize.ts --outdir=lib --bundle --format=esm --packages=external", + "build:props": "generate-html-props-meta src/__generated__/html-props-meta.ts --convertName=react", "dts": "tsc --project tsconfig.dts.json", "typecheck": "tsc", "test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests", @@ -19,6 +20,7 @@ "@types/react": "^18.2.21", "@types/react-dom": "^18.2.7", "@webstudio-is/jest-config": "workspace:*", + "@webstudio-is/html-data": "workspace:*", "@webstudio-is/tsconfig": "workspace:*", "jest": "^29.6.4", "react": "^18.2.0", diff --git a/packages/react-sdk/src/__generated__/html-props-meta.ts b/packages/react-sdk/src/__generated__/html-props-meta.ts new file mode 100644 index 000000000000..41ddabd8f099 --- /dev/null +++ b/packages/react-sdk/src/__generated__/html-props-meta.ts @@ -0,0 +1,1981 @@ +import type { PropMeta } from "@webstudio-is/sdk"; + +const globals: Record = { + accessKey: { + type: "string", + control: "text", + required: false, + description: "Keyboard shortcut to activate or add focus to the element.", + }, + autoCapitalize: { + type: "string", + control: "select", + required: false, + options: ["on", "off", "none", "sentences", "words", "characters"], + description: + "Sets whether input is automatically capitalized when entered by user.", + }, + autoFocus: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates that an element should be focused on page load, or when its parent dialog is displayed.", + }, + className: { + type: "string", + control: "text", + required: false, + description: + "Often used with CSS to style elements with common properties.", + }, + contentEditable: { + type: "string", + control: "radio", + required: false, + options: ["true", "plaintext-only", "false"], + description: "Indicates whether the element's content is editable.", + }, + dir: { + type: "string", + control: "radio", + required: false, + options: ["ltr", "rtl", "auto"], + description: + "Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)", + }, + draggable: { + type: "string", + control: "radio", + required: false, + options: ["true", "false"], + description: "Defines whether the element can be dragged.", + }, + enterKeyHint: { + type: "string", + control: "select", + required: false, + options: ["enter", "done", "go", "next", "previous", "search", "send"], + description: + "The enterkeyhint specifies what action label (or icon) to present for the enter key onvirtual keyboards. The attribute can be used with form controls (such asthe value of textarea elements), or in elements in anediting host (e.g., using contenteditable attribute).", + }, + hidden: { + type: "string", + control: "radio", + required: false, + options: ["until-found", "hidden"], + description: + "Prevents rendering of given element, while keeping child elements, e.g. script elements, active.", + }, + id: { + type: "string", + control: "text", + required: false, + description: + "Often used with CSS to style a specific element. The value of this attribute must be unique.", + }, + inert: { type: "boolean", control: "boolean", required: false }, + inputMode: { + type: "string", + control: "select", + required: false, + options: [ + "none", + "text", + "tel", + "email", + "url", + "numeric", + "decimal", + "search", + ], + description: + "Provides a hint as to the type of data that might be entered by the user while editing the element or its contents. The attribute can be used with form controls (such as the value oftextarea elements), or in elements in an editing host (e.g., using contenteditable attribute).", + }, + is: { type: "string", control: "text", required: false }, + itemID: { type: "string", control: "text", required: false }, + itemProp: { type: "string", control: "text", required: false }, + itemRef: { type: "string", control: "text", required: false }, + itemScope: { type: "boolean", control: "boolean", required: false }, + itemType: { type: "string", control: "text", required: false }, + lang: { + type: "string", + control: "text", + required: false, + description: "Defines the language used in the element.", + }, + nonce: { type: "string", control: "text", required: false }, + popover: { + type: "string", + control: "radio", + required: false, + options: ["auto", "manual"], + }, + slot: { + type: "string", + control: "text", + required: false, + description: "Assigns a slot in a shadow DOM shadow tree to an element.", + }, + spellCheck: { + type: "string", + control: "radio", + required: false, + options: ["true", "false"], + description: "Indicates whether spell checking is allowed for the element.", + }, + style: { + type: "string", + control: "text", + required: false, + description: + "Defines CSS styles which will override styles previously set.", + }, + tabIndex: { + type: "number", + control: "number", + required: false, + description: + "Overrides the browser's default tab order and follows the one specified instead.", + }, + title: { + type: "string", + control: "text", + required: false, + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, + translate: { + type: "string", + control: "radio", + required: false, + options: ["yes", "no"], + description: + "Specify whether an element's attribute values and the values of its text node children are to be translated when the page is localized, or whether to leave them unchanged.", + }, +}; + +export const a = { + ...globals, + download: { + type: "string", + control: "text", + required: false, + description: + "Indicates that the hyperlink is to be used for downloading a resource.", + }, + href: { + type: "string", + control: "text", + required: false, + description: "The URL of a linked resource.", + }, + hrefLang: { + type: "string", + control: "text", + required: false, + description: "Specifies the language of the linked resource.", + }, + ping: { + type: "string", + control: "text", + required: false, + description: + "The ping attribute specifies a space-separated list of URLs to be notified if a user follows the hyperlink.", + }, + referrerPolicy: { + type: "string", + control: "text", + required: false, + description: "Specifies which referrer is sent when fetching the resource.", + }, + rel: { + type: "string", + control: "text", + required: false, + description: + "Specifies the relationship of the target object to the link object.", + }, + target: { + type: "string", + control: "text", + required: false, + description: + "Specifies where to open the linked document (in the case of an element) or where to display the response received (in the case of a element)", + }, + type: { + type: "string", + control: "text", + required: false, + description: "Defines the type of the element.", + }, +}; + +export const abbr = { + ...globals, + title: { + type: "string", + control: "text", + required: false, + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, +}; + +export const address = globals; + +export const area = { + ...globals, + alt: { + type: "string", + control: "text", + required: false, + description: + "Text description of the image, which is very important for accessibility and search engine optimization. Screen readers read this description to users so they know what the image means. Alt text is also displayed on the page if the image can't be loaded for some reason.", + }, + coords: { + type: "number", + control: "number", + required: false, + description: + "A set of values specifying the coordinates of the hot-spot region.", + }, + download: { + type: "string", + control: "text", + required: false, + description: + "Indicates that the hyperlink is to be used for downloading a resource.", + }, + href: { + type: "string", + control: "text", + required: false, + description: "The URL of a linked resource.", + }, + ping: { + type: "string", + control: "text", + required: false, + description: + "The ping attribute specifies a space-separated list of URLs to be notified if a user follows the hyperlink.", + }, + referrerPolicy: { + type: "string", + control: "text", + required: false, + description: "Specifies which referrer is sent when fetching the resource.", + }, + rel: { + type: "string", + control: "text", + required: false, + description: + "Specifies the relationship of the target object to the link object.", + }, + shape: { + type: "string", + control: "select", + required: false, + options: ["circle", "default", "poly", "rect"], + }, + target: { + type: "string", + control: "text", + required: false, + description: + "Specifies where to open the linked document (in the case of an element) or where to display the response received (in the case of a element)", + }, +}; + +export const article = globals; + +export const aside = globals; + +export const audio = { + ...globals, + autoPlay: { + type: "boolean", + control: "boolean", + required: false, + description: "The audio or video should play as soon as possible.", + }, + controls: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether the browser should show playback controls to the user.", + }, + crossOrigin: { + type: "string", + control: "radio", + required: false, + options: ["anonymous", "use-credentials"], + description: "How the element handles cross-origin requests", + }, + loop: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether the media should start playing from the start when it's finished.", + }, + muted: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether the audio will be initially silenced on page load.", + }, + preload: { + type: "string", + control: "radio", + required: false, + options: ["none", "metadata", "auto"], + description: + "Indicates whether the whole resource, parts of it or nothing should be preloaded.", + }, + src: { + type: "string", + control: "text", + required: false, + description: "The URL of the embeddable content.", + }, +}; + +export const b = globals; + +export const base = { + ...globals, + href: { + type: "string", + control: "text", + required: false, + description: "The URL of a linked resource.", + }, + target: { + type: "string", + control: "text", + required: false, + description: + "Specifies where to open the linked document (in the case of an element) or where to display the response received (in the case of a element)", + }, +}; + +export const bdi = globals; + +export const bdo = { + ...globals, + dir: { + type: "string", + control: "radio", + required: false, + options: ["ltr", "rtl"], + description: + "Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)", + }, +}; + +export const blockquote = { + ...globals, + cite: { + type: "string", + control: "text", + required: false, + description: + "Contains a URI which points to the source of the quote or change.", + }, +}; + +export const body = globals; + +export const br = globals; + +export const button = { + ...globals, + disabled: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates whether the user can interact with the element.", + }, + form: { + type: "string", + control: "text", + required: false, + description: "Indicates the form that is the owner of the element.", + }, + formAction: { + type: "string", + control: "text", + required: false, + description: + "Indicates the action of the element, overriding the action defined inthe form.", + }, + formEncType: { + type: "string", + control: "radio", + required: false, + options: [ + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain", + ], + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute sets the encoding type to use during form submission. If this attribute is specified, it overrides theenctype attribute of the button\'s form owner.', + }, + formMethod: { + type: "string", + control: "radio", + required: false, + options: ["GET", "POST", "dialog"], + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute sets the submission method to use during form submission (GET, POST, etc.). If this attribute is specified, it overrides the method attribute of the button\'s form owner.', + }, + formNoValidate: { + type: "boolean", + control: "boolean", + required: false, + description: + 'If the button/input is a submit button (e.g. type="submit"), this boolean attribute specifies that the form is not to be validatedwhen it is submitted. If this attribute is specified, it overrides thenovalidate attribute of the button\'s form owner.', + }, + formTarget: { + type: "string", + control: "text", + required: false, + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute specifies the browsing context (for example, tab, window, or inline frame) in which to display the response that is received aftersubmitting the form. If this attribute is specified, it overrides thetarget attribute of the button\'s form owner.', + }, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + popovertarget: { type: "string", control: "text", required: false }, + popovertargetaction: { + type: "string", + control: "radio", + required: false, + options: ["toggle", "show", "hide"], + }, + type: { + type: "string", + control: "radio", + required: false, + options: ["submit", "reset", "button"], + description: "Defines the type of the element.", + }, + value: { + type: "string", + control: "text", + required: false, + description: + "Defines a default value which will be displayed in the element on pageload.", + }, +}; + +export const canvas = { + ...globals, + height: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s height in pixels.", + }, + width: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s width in pixels.", + }, +}; + +export const caption = globals; + +export const cite = globals; + +export const code = globals; + +export const col = { + ...globals, + span: { type: "number", control: "number", required: false }, +}; + +export const colgroup = { + ...globals, + span: { type: "number", control: "number", required: false }, +}; + +export const data = { + ...globals, + value: { + type: "string", + control: "text", + required: false, + description: + "Defines a default value which will be displayed in the element on pageload.", + }, +}; + +export const datalist = globals; + +export const dd = globals; + +export const del = { + ...globals, + cite: { + type: "string", + control: "text", + required: false, + description: + "Contains a URI which points to the source of the quote or change.", + }, + dateTime: { + type: "string", + control: "text", + required: false, + description: "Indicates the date and time associated with the element.", + }, +}; + +export const details = { + ...globals, + open: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether the contents are currently visible (in the case of a
element) or whether the dialog is active and can be interacted with (in the case of a element).", + }, +}; + +export const dfn = { + ...globals, + title: { + type: "string", + control: "text", + required: false, + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, +}; + +export const dialog = { + ...globals, + open: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether the contents are currently visible (in the case of a
element) or whether the dialog is active and can be interacted with (in the case of a element).", + }, +}; + +export const div = globals; + +export const dl = globals; + +export const dt = globals; + +export const em = globals; + +export const embed = { + ...globals, + height: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s height in pixels.", + }, + src: { + type: "string", + control: "text", + required: false, + description: "The URL of the embeddable content.", + }, + type: { + type: "string", + control: "text", + required: false, + description: "Defines the type of the element.", + }, + width: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s width in pixels.", + }, +}; + +export const fieldset = { + ...globals, + disabled: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates whether the user can interact with the element.", + }, + form: { + type: "string", + control: "text", + required: false, + description: "Indicates the form that is the owner of the element.", + }, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, +}; + +export const figcaption = globals; + +export const figure = globals; + +export const footer = globals; + +export const form = { + ...globals, + acceptCharset: { + type: "string", + control: "text", + required: false, + description: "List of supported charsets.", + }, + action: { + type: "string", + control: "text", + required: false, + description: + "The URI of a program that processes the information submitted via the form.", + }, + autoComplete: { + type: "string", + control: "radio", + required: false, + options: ["on", "off"], + description: + "Indicates whether controls in this form can by default have their valuesautomatically completed by the browser.", + }, + encType: { + type: "string", + control: "radio", + required: false, + options: [ + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain", + ], + description: + "Defines the content type of the form data when themethod is POST.", + }, + method: { + type: "string", + control: "radio", + required: false, + options: ["GET", "POST", "dialog"], + description: + "Defines which HTTP method to use when submitting the form. Can be GET (default) or POST.", + }, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + noValidate: { + type: "boolean", + control: "boolean", + required: false, + description: + "This attribute indicates that the form shouldn't be validated when submitted.", + }, + target: { + type: "string", + control: "text", + required: false, + description: + "Specifies where to open the linked document (in the case of an element) or where to display the response received (in the case of a element)", + }, +}; + +export const h1 = globals; + +export const h2 = globals; + +export const h3 = globals; + +export const h4 = globals; + +export const h5 = globals; + +export const h6 = globals; + +export const head = globals; + +export const header = globals; + +export const hgroup = globals; + +export const hr = globals; + +export const html = globals; + +export const i = globals; + +export const iframe = { + ...globals, + allow: { + type: "string", + control: "text", + required: false, + description: "Specifies a feature-policy for the iframe.", + }, + allowFullScreen: { type: "boolean", control: "boolean", required: false }, + height: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s height in pixels.", + }, + loading: { + type: "string", + control: "radio", + required: false, + options: ["lazy", "eager"], + description: + "Determines whether the image will load as soon as possible (Eager), or when it scrolls into view (Lazy). Lazy loading is a great option for pages with many images because it can significantly reduce the time it takes for the page to load initially.", + }, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + referrerPolicy: { + type: "string", + control: "text", + required: false, + description: "Specifies which referrer is sent when fetching the resource.", + }, + sandbox: { + type: "string", + control: "text", + required: false, + description: + "Stops a document loaded in an iframe from using certain features (such as submitting forms or opening new windows).", + }, + src: { + type: "string", + control: "text", + required: false, + description: "The URL of the embeddable content.", + }, + srcDoc: { type: "string", control: "text", required: false }, + width: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s width in pixels.", + }, +}; + +export const img = { + ...globals, + alt: { + type: "string", + control: "text", + required: false, + description: + "Text description of the image, which is very important for accessibility and search engine optimization. Screen readers read this description to users so they know what the image means. Alt text is also displayed on the page if the image can't be loaded for some reason.", + }, + crossOrigin: { + type: "string", + control: "radio", + required: false, + options: ["anonymous", "use-credentials"], + description: "How the element handles cross-origin requests", + }, + decoding: { + type: "string", + control: "radio", + required: false, + options: ["sync", "async", "auto"], + description: "Indicates the preferred method to decode the image.", + }, + fetchPriority: { + type: "string", + control: "radio", + required: false, + options: ["auto", "high", "low"], + }, + height: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s height in pixels.", + }, + ismap: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates that the image is part of a server-side image map.", + }, + loading: { + type: "string", + control: "radio", + required: false, + options: ["lazy", "eager"], + description: + "Determines whether the image will load as soon as possible (Eager), or when it scrolls into view (Lazy). Lazy loading is a great option for pages with many images because it can significantly reduce the time it takes for the page to load initially.", + }, + referrerPolicy: { + type: "string", + control: "text", + required: false, + description: "Specifies which referrer is sent when fetching the resource.", + }, + sizes: { type: "string", control: "text", required: false }, + src: { + type: "string", + control: "text", + required: false, + description: "The URL of the embeddable content.", + }, + srcSet: { + type: "string", + control: "text", + required: false, + description: "One or more responsive image candidates.", + }, + useMap: { type: "string", control: "text", required: false }, + width: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s width in pixels.", + }, +}; + +export const input = { + ...globals, + accept: { + type: "string", + control: "text", + required: false, + description: "List of types the server accepts, typically a file type.", + }, + alt: { + type: "string", + control: "text", + required: false, + description: + "Text description of the image, which is very important for accessibility and search engine optimization. Screen readers read this description to users so they know what the image means. Alt text is also displayed on the page if the image can't be loaded for some reason.", + }, + autoComplete: { + type: "string", + control: "text", + required: false, + description: + "Indicates whether controls in this form can by default have their valuesautomatically completed by the browser.", + }, + checked: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether the element should be checked on page load.", + }, + dirname: { type: "string", control: "text", required: false }, + disabled: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates whether the user can interact with the element.", + }, + form: { + type: "string", + control: "text", + required: false, + description: "Indicates the form that is the owner of the element.", + }, + formAction: { + type: "string", + control: "text", + required: false, + description: + "Indicates the action of the element, overriding the action defined inthe form.", + }, + formEncType: { + type: "string", + control: "radio", + required: false, + options: [ + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain", + ], + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute sets the encoding type to use during form submission. If this attribute is specified, it overrides theenctype attribute of the button\'s form owner.', + }, + formMethod: { + type: "string", + control: "radio", + required: false, + options: ["GET", "POST", "dialog"], + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute sets the submission method to use during form submission (GET, POST, etc.). If this attribute is specified, it overrides the method attribute of the button\'s form owner.', + }, + formNoValidate: { + type: "boolean", + control: "boolean", + required: false, + description: + 'If the button/input is a submit button (e.g. type="submit"), this boolean attribute specifies that the form is not to be validatedwhen it is submitted. If this attribute is specified, it overrides thenovalidate attribute of the button\'s form owner.', + }, + formTarget: { + type: "string", + control: "text", + required: false, + description: + 'If the button/input is a submit button (e.g. type="submit"), this attribute specifies the browsing context (for example, tab, window, or inline frame) in which to display the response that is received aftersubmitting the form. If this attribute is specified, it overrides thetarget attribute of the button\'s form owner.', + }, + height: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s height in pixels.", + }, + list: { + type: "string", + control: "text", + required: false, + description: + "Identifies a list of pre-defined options to suggest to the user.", + }, + max: { + type: "string", + control: "text", + required: false, + description: "Indicates the maximum value allowed.", + }, + maxLength: { + type: "number", + control: "number", + required: false, + description: + "Defines the maximum number of characters allowed in the element.", + }, + min: { + type: "string", + control: "text", + required: false, + description: "Indicates the minimum value allowed.", + }, + minLength: { + type: "number", + control: "number", + required: false, + description: + "Defines the minimum number of characters allowed in the element.", + }, + multiple: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether multiple values can be entered in an input of the type email or file.", + }, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + pattern: { + type: "string", + control: "text", + required: false, + description: + "Defines a regular expression which the element's value will be validated against.", + }, + placeholder: { + type: "string", + control: "text", + required: false, + description: + "Provides a hint to the user of what can be entered in the field.", + }, + popovertarget: { type: "string", control: "text", required: false }, + popovertargetaction: { + type: "string", + control: "radio", + required: false, + options: ["toggle", "show", "hide"], + }, + readOnly: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates whether the element can be edited.", + }, + required: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether this form element must be filled before the form can be submitted.", + }, + size: { + type: "number", + control: "number", + required: false, + description: + "Defines the width of the element (in pixels). If the element'stype attribute is text or password then it's the number of characters.", + }, + src: { + type: "string", + control: "text", + required: false, + description: "The URL of the embeddable content.", + }, + step: { type: "number", control: "number", required: false }, + title: { + type: "string", + control: "text", + required: false, + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, + type: { + type: "string", + control: "text", + required: false, + description: "Defines the type of the element.", + }, + value: { + type: "string", + control: "text", + required: false, + description: + "Defines a default value which will be displayed in the element on pageload.", + }, + width: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s width in pixels.", + }, +}; + +export const ins = { + ...globals, + cite: { + type: "string", + control: "text", + required: false, + description: + "Contains a URI which points to the source of the quote or change.", + }, + dateTime: { + type: "string", + control: "text", + required: false, + description: "Indicates the date and time associated with the element.", + }, +}; + +export const kbd = globals; + +export const label = { + ...globals, + htmlFor: { + type: "string", + control: "text", + required: false, + description: + "Associates this Label with an Input. The value of the “For” attribute should match the ID attribute of the corresponding Input element", + }, +}; + +export const legend = globals; + +export const li = { + ...globals, + value: { + type: "number", + control: "number", + required: false, + description: + "Defines a default value which will be displayed in the element on pageload.", + }, +}; + +export const link = { + ...globals, + as: { type: "string", control: "radio", required: false, options: [] }, + blocking: { type: "string", control: "text", required: false }, + color: { + type: "string", + control: "text", + required: false, + description: + "This attribute sets the text color using either a named color or a color specified in the hexadecimal #RRGGBB format. Note: This is a legacy attribute. Please use the CSS color property instead.", + }, + crossOrigin: { + type: "string", + control: "radio", + required: false, + options: ["anonymous", "use-credentials"], + description: "How the element handles cross-origin requests", + }, + disabled: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates whether the user can interact with the element.", + }, + fetchPriority: { + type: "string", + control: "radio", + required: false, + options: ["auto", "high", "low"], + }, + href: { + type: "string", + control: "text", + required: false, + description: "The URL of a linked resource.", + }, + hrefLang: { + type: "string", + control: "text", + required: false, + description: "Specifies the language of the linked resource.", + }, + imageSizes: { type: "string", control: "text", required: false }, + imageSrcSet: { type: "string", control: "text", required: false }, + integrity: { + type: "string", + control: "text", + required: false, + description: + "Specifies a Subresource Integrity value that allows browsers to verify what they fetch.", + }, + media: { + type: "string", + control: "text", + required: false, + description: + "Specifies a hint of the media for which the linked resource was designed.", + }, + referrerPolicy: { + type: "string", + control: "text", + required: false, + description: "Specifies which referrer is sent when fetching the resource.", + }, + rel: { + type: "string", + control: "text", + required: false, + description: + "Specifies the relationship of the target object to the link object.", + }, + sizes: { type: "string", control: "text", required: false }, + title: { + type: "string", + control: "text", + required: false, + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, + type: { + type: "string", + control: "text", + required: false, + description: "Defines the type of the element.", + }, +}; + +export const main = globals; + +export const map = { + ...globals, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, +}; + +export const mark = globals; + +export const math = globals; + +export const menu = globals; + +export const menuitem = globals; + +export const meta = { + ...globals, + charSet: { + type: "string", + control: "text", + required: false, + description: "Declares the character encoding of the page or script.", + }, + content: { + type: "string", + control: "text", + required: false, + description: + "A value associated with http-equiv orname depending on the context.", + }, + httpEquiv: { + type: "string", + control: "select", + required: false, + options: [ + "content-type", + "default-style", + "refresh", + "x-ua-compatible", + "content-security-policy", + ], + description: "Defines a pragma directive.", + }, + media: { + type: "string", + control: "text", + required: false, + description: + "Specifies a hint of the media for which the linked resource was designed.", + }, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, +}; + +export const meter = { + ...globals, + high: { + type: "number", + control: "number", + required: false, + description: "Indicates the lower bound of the upper range.", + }, + low: { + type: "number", + control: "number", + required: false, + description: "Indicates the upper bound of the lower range.", + }, + max: { + type: "number", + control: "number", + required: false, + description: "Indicates the maximum value allowed.", + }, + min: { + type: "number", + control: "number", + required: false, + description: "Indicates the minimum value allowed.", + }, + optimum: { + type: "number", + control: "number", + required: false, + description: "Indicates the optimal numeric value.", + }, + value: { + type: "number", + control: "number", + required: false, + description: + "Defines a default value which will be displayed in the element on pageload.", + }, +}; + +export const nav = globals; + +export const noscript = globals; + +export const object = { + ...globals, + data: { + type: "string", + control: "text", + required: false, + description: "Specifies the URL of the resource.", + }, + form: { + type: "string", + control: "text", + required: false, + description: "Indicates the form that is the owner of the element.", + }, + height: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s height in pixels.", + }, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + type: { + type: "string", + control: "text", + required: false, + description: "Defines the type of the element.", + }, + width: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s width in pixels.", + }, +}; + +export const ol = { + ...globals, + reversed: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether the list should be displayed in a descending order instead of an ascending order.", + }, + start: { + type: "number", + control: "number", + required: false, + description: "Defines the first number if other than 1.", + }, + type: { + type: "string", + control: "select", + required: false, + options: ["1", "a", "A", "i", "I"], + description: "Defines the type of the element.", + }, +}; + +export const optgroup = { + ...globals, + disabled: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates whether the user can interact with the element.", + }, + label: { + type: "string", + control: "text", + required: false, + description: "Specifies a user-readable title of the element.", + }, +}; + +export const option = { + ...globals, + disabled: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates whether the user can interact with the element.", + }, + label: { + type: "string", + control: "text", + required: false, + description: "Specifies a user-readable title of the element.", + }, + selected: { + type: "boolean", + control: "boolean", + required: false, + description: "Defines a value which will be selected on page load.", + }, + value: { + type: "string", + control: "text", + required: false, + description: + "Defines a default value which will be displayed in the element on pageload.", + }, +}; + +export const output = { + ...globals, + htmlFor: { + type: "string", + control: "text", + required: false, + description: + "Associates this Label with an Input. The value of the “For” attribute should match the ID attribute of the corresponding Input element", + }, + form: { + type: "string", + control: "text", + required: false, + description: "Indicates the form that is the owner of the element.", + }, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, +}; + +export const p = globals; + +export const param = globals; + +export const picture = globals; + +export const pre = globals; + +export const progress = { + ...globals, + max: { + type: "number", + control: "number", + required: false, + description: "Indicates the maximum value allowed.", + }, + value: { + type: "number", + control: "number", + required: false, + description: + "Defines a default value which will be displayed in the element on pageload.", + }, +}; + +export const q = { + ...globals, + cite: { + type: "string", + control: "text", + required: false, + description: + "Contains a URI which points to the source of the quote or change.", + }, +}; + +export const rb = globals; + +export const rp = globals; + +export const rt = globals; + +export const rtc = globals; + +export const ruby = globals; + +export const s = globals; + +export const samp = globals; + +export const script = { + ...globals, + async: { + type: "boolean", + control: "boolean", + required: false, + description: "Executes the script asynchronously.", + }, + blocking: { type: "string", control: "text", required: false }, + crossOrigin: { + type: "string", + control: "radio", + required: false, + options: ["anonymous", "use-credentials"], + description: "How the element handles cross-origin requests", + }, + defer: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates that the script should be executed after the page has beenparsed.", + }, + fetchPriority: { + type: "string", + control: "radio", + required: false, + options: ["auto", "high", "low"], + }, + integrity: { + type: "string", + control: "text", + required: false, + description: + "Specifies a Subresource Integrity value that allows browsers to verify what they fetch.", + }, + noModule: { type: "boolean", control: "boolean", required: false }, + referrerPolicy: { + type: "string", + control: "text", + required: false, + description: "Specifies which referrer is sent when fetching the resource.", + }, + src: { + type: "string", + control: "text", + required: false, + description: "The URL of the embeddable content.", + }, + type: { + type: "string", + control: "radio", + required: false, + options: ["module"], + description: "Defines the type of the element.", + }, +}; + +export const search = globals; + +export const section = globals; + +export const select = { + ...globals, + autoComplete: { + type: "string", + control: "text", + required: false, + description: + "Indicates whether controls in this form can by default have their valuesautomatically completed by the browser.", + }, + disabled: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates whether the user can interact with the element.", + }, + form: { + type: "string", + control: "text", + required: false, + description: "Indicates the form that is the owner of the element.", + }, + multiple: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether multiple values can be entered in an input of the type email or file.", + }, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + required: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether this form element must be filled before the form can be submitted.", + }, + size: { + type: "number", + control: "number", + required: false, + description: + "Defines the width of the element (in pixels). If the element'stype attribute is text or password then it's the number of characters.", + }, +}; + +export const slot = { + ...globals, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, +}; + +export const small = globals; + +export const source = { + ...globals, + height: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s height in pixels.", + }, + media: { + type: "string", + control: "text", + required: false, + description: + "Specifies a hint of the media for which the linked resource was designed.", + }, + sizes: { type: "string", control: "text", required: false }, + src: { + type: "string", + control: "text", + required: false, + description: "The URL of the embeddable content.", + }, + srcSet: { + type: "string", + control: "text", + required: false, + description: "One or more responsive image candidates.", + }, + type: { + type: "string", + control: "text", + required: false, + description: "Defines the type of the element.", + }, + width: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s width in pixels.", + }, +}; + +export const span = globals; + +export const strong = globals; + +export const style = { + ...globals, + blocking: { type: "string", control: "text", required: false }, + media: { + type: "string", + control: "text", + required: false, + description: + "Specifies a hint of the media for which the linked resource was designed.", + }, + title: { + type: "string", + control: "text", + required: false, + description: + "Text to be displayed in a tooltip when hovering over the element.", + }, +}; + +export const sub = globals; + +export const summary = globals; + +export const sup = globals; + +export const svg = globals; + +export const table = globals; + +export const tbody = globals; + +export const td = { + ...globals, + colSpan: { + type: "number", + control: "number", + required: false, + description: + "The colspan attribute defines the number of columns a cell should span.", + }, + headers: { + type: "string", + control: "text", + required: false, + description: "IDs of the elements which applies to this element.", + }, + rowSpan: { + type: "number", + control: "number", + required: false, + description: "Defines the number of rows a table cell should span over.", + }, +}; + +export const template = globals; + +export const textarea = { + ...globals, + autoComplete: { + type: "string", + control: "text", + required: false, + description: + "Indicates whether controls in this form can by default have their valuesautomatically completed by the browser.", + }, + cols: { + type: "number", + control: "number", + required: false, + description: "Defines the number of columns in a textarea.", + }, + dirname: { type: "string", control: "text", required: false }, + disabled: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates whether the user can interact with the element.", + }, + form: { + type: "string", + control: "text", + required: false, + description: "Indicates the form that is the owner of the element.", + }, + maxLength: { + type: "number", + control: "number", + required: false, + description: + "Defines the maximum number of characters allowed in the element.", + }, + minLength: { + type: "number", + control: "number", + required: false, + description: + "Defines the minimum number of characters allowed in the element.", + }, + name: { + type: "string", + control: "text", + required: false, + description: + "This name is important when submitting form data to the server, as it identifies the data associated with the input. When multiple inputs share the same name attribute, they are treated as part of the same group (e.g., radio buttons or checkboxes).", + }, + placeholder: { + type: "string", + control: "text", + required: false, + description: + "Provides a hint to the user of what can be entered in the field.", + }, + readOnly: { + type: "boolean", + control: "boolean", + required: false, + description: "Indicates whether the element can be edited.", + }, + required: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether this form element must be filled before the form can be submitted.", + }, + rows: { + type: "number", + control: "number", + required: false, + description: "Defines the number of rows in a text area.", + }, + wrap: { + type: "string", + control: "radio", + required: false, + options: ["soft", "hard"], + description: "Indicates whether the text should be wrapped.", + }, +}; + +export const tfoot = globals; + +export const th = { + ...globals, + abbr: { type: "string", control: "text", required: false }, + colSpan: { + type: "number", + control: "number", + required: false, + description: + "The colspan attribute defines the number of columns a cell should span.", + }, + headers: { + type: "string", + control: "text", + required: false, + description: "IDs of the elements which applies to this element.", + }, + rowSpan: { + type: "number", + control: "number", + required: false, + description: "Defines the number of rows a table cell should span over.", + }, + scope: { + type: "string", + control: "select", + required: false, + options: ["row", "col", "rowgroup", "colgroup"], + description: + "Defines the cells that the header test (defined in theth element) relates to.", + }, +}; + +export const thead = globals; + +export const time = { + ...globals, + dateTime: { + type: "number", + control: "number", + required: false, + description: "Indicates the date and time associated with the element.", + }, +}; + +export const title = globals; + +export const tr = globals; + +export const track = { + ...globals, + default: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates that the track should be enabled unless the user's preferencesindicate something different.", + }, + kind: { + type: "string", + control: "select", + required: false, + options: ["subtitles", "captions", "descriptions", "chapters", "metadata"], + description: "Specifies the kind of text track.", + }, + label: { + type: "string", + control: "text", + required: false, + description: "Specifies a user-readable title of the element.", + }, + src: { + type: "string", + control: "text", + required: false, + description: "The URL of the embeddable content.", + }, + srcLang: { type: "string", control: "text", required: false }, +}; + +export const u = globals; + +export const ul = globals; + +const _var = globals; +export { _var as var }; + +export const video = { + ...globals, + autoPlay: { + type: "boolean", + control: "boolean", + required: false, + description: "The audio or video should play as soon as possible.", + }, + controls: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether the browser should show playback controls to the user.", + }, + crossOrigin: { + type: "string", + control: "radio", + required: false, + options: ["anonymous", "use-credentials"], + description: "How the element handles cross-origin requests", + }, + height: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s height in pixels.", + }, + loop: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether the media should start playing from the start when it's finished.", + }, + muted: { + type: "boolean", + control: "boolean", + required: false, + description: + "Indicates whether the audio will be initially silenced on page load.", + }, + playsInline: { + type: "boolean", + control: "boolean", + required: false, + description: + 'A Boolean attribute indicating that the video is to be played "inline"; that is, within the element\'s playback area. Note that the absence of this attribute does not imply that the video will always be played in fullscreen.', + }, + poster: { + type: "string", + control: "text", + required: false, + description: + "A URL indicating a poster frame to show until the user plays or seeks.", + }, + preload: { + type: "string", + control: "radio", + required: false, + options: ["none", "metadata", "auto"], + description: + "Indicates whether the whole resource, parts of it or nothing should be preloaded.", + }, + src: { + type: "string", + control: "text", + required: false, + description: "The URL of the embeddable content.", + }, + width: { + type: "number", + control: "number", + required: false, + description: "Defines the image’s width in pixels.", + }, +}; + +export const wbr = globals; diff --git a/packages/react-sdk/src/components/component-meta.ts b/packages/react-sdk/src/components/component-meta.ts index 124465770e3a..bf0978b2a6c6 100644 --- a/packages/react-sdk/src/components/component-meta.ts +++ b/packages/react-sdk/src/components/component-meta.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { PropMeta } from "../prop-meta"; +import { PropMeta } from "@webstudio-is/sdk"; import type { htmlTags as HtmlTags } from "html-tags"; import { EmbedTemplateStyleDecl, WsEmbedTemplate } from "../embed-template"; diff --git a/packages/react-sdk/src/index.ts b/packages/react-sdk/src/index.ts index 86044a79acf8..a98b85222fc8 100644 --- a/packages/react-sdk/src/index.ts +++ b/packages/react-sdk/src/index.ts @@ -2,7 +2,6 @@ export * from "./css/index"; export * from "./tree/index"; export * from "./app/index"; export * from "./components/components-utils"; -export { PropMeta } from "./prop-meta"; export { type WsComponentPropsMeta, type ComponentState, diff --git a/packages/sdk-components-react-radix/package.json b/packages/sdk-components-react-radix/package.json index 5f181729a2ff..5a51c9ac5b7d 100644 --- a/packages/sdk-components-react-radix/package.json +++ b/packages/sdk-components-react-radix/package.json @@ -41,7 +41,7 @@ "scripts": { "dev": "rm -rf lib && esbuild 'src/**/*.ts' 'src/**/*.tsx' --outdir=lib --watch", "build": "rm -rf lib && esbuild src/components.ts src/metas.ts src/props.ts src/hooks.ts --outdir=lib --bundle --format=esm --packages=external", - "build:args": "NODE_OPTIONS=--conditions=webstudio generate-arg-types './src/accordion.tsx !./src/*.stories.tsx !./src/*.ws.tsx' -e asChild -e modal -e defaultValue -e defaultOpen -e defaultChecked && prettier --write \"**/*.props.ts\"", + "build:args": "NODE_OPTIONS=--conditions=webstudio generate-arg-types './src/*.tsx !./src/*.stories.tsx !./src/*.ws.tsx' -e asChild -e modal -e defaultValue -e defaultOpen -e defaultChecked && prettier --write \"**/*.props.ts\"", "build:tailwind": "tsx scripts/generate-tailwind-theme.ts && prettier --write src/theme/__generated__", "build:stories": "webstudio-sdk generate-stories && prettier --write \"src/__generated__/*.stories.tsx\"", "dts": "tsc --project tsconfig.dts.json", @@ -69,7 +69,8 @@ "@radix-ui/react-tooltip": "^1.0.6", "@webstudio-is/css-engine": "workspace:*", "@webstudio-is/icons": "workspace:*", - "@webstudio-is/react-sdk": "workspace:*" + "@webstudio-is/react-sdk": "workspace:*", + "@webstudio-is/sdk": "workspace:*" }, "devDependencies": { "@storybook/react": "^7.4.0", diff --git a/packages/sdk-components-react-radix/src/__generated__/accordion.props.ts b/packages/sdk-components-react-radix/src/__generated__/accordion.props.ts index f46a23e78371..f666997655ab 100644 --- a/packages/sdk-components-react-radix/src/__generated__/accordion.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/accordion.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsAccordion: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react-radix/src/__generated__/checkbox.props.ts b/packages/sdk-components-react-radix/src/__generated__/checkbox.props.ts index db19f434107a..fa067c56ae97 100644 --- a/packages/sdk-components-react-radix/src/__generated__/checkbox.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/checkbox.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsCheckbox: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react-radix/src/__generated__/collapsible.props.ts b/packages/sdk-components-react-radix/src/__generated__/collapsible.props.ts index 605ee45f0564..ee852fe9af5e 100644 --- a/packages/sdk-components-react-radix/src/__generated__/collapsible.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/collapsible.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsCollapsible: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react-radix/src/__generated__/dialog.props.ts b/packages/sdk-components-react-radix/src/__generated__/dialog.props.ts index 0cd9554da654..7bcd18964969 100644 --- a/packages/sdk-components-react-radix/src/__generated__/dialog.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/dialog.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsDialog: Record = { open: { diff --git a/packages/sdk-components-react-radix/src/__generated__/label.props.ts b/packages/sdk-components-react-radix/src/__generated__/label.props.ts index b1637051c03f..3f72630426c1 100644 --- a/packages/sdk-components-react-radix/src/__generated__/label.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/label.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react-radix/src/__generated__/navigation-menu.props.ts b/packages/sdk-components-react-radix/src/__generated__/navigation-menu.props.ts index b29198751929..d672a4574a0a 100644 --- a/packages/sdk-components-react-radix/src/__generated__/navigation-menu.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/navigation-menu.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsNavigationMenu: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react-radix/src/__generated__/popover.props.ts b/packages/sdk-components-react-radix/src/__generated__/popover.props.ts index 5df7f10d3caf..daa8e824ad82 100644 --- a/packages/sdk-components-react-radix/src/__generated__/popover.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/popover.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsPopover: Record = { open: { diff --git a/packages/sdk-components-react-radix/src/__generated__/radio-group.props.ts b/packages/sdk-components-react-radix/src/__generated__/radio-group.props.ts index a41c2e708153..88522b997c06 100644 --- a/packages/sdk-components-react-radix/src/__generated__/radio-group.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/radio-group.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsRadioGroup: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react-radix/src/__generated__/select.props.ts b/packages/sdk-components-react-radix/src/__generated__/select.props.ts index 5f76d747f31d..e6bf4fd7547b 100644 --- a/packages/sdk-components-react-radix/src/__generated__/select.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/select.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsSelect: Record = { autoComplete: { diff --git a/packages/sdk-components-react-radix/src/__generated__/sheet.props.ts b/packages/sdk-components-react-radix/src/__generated__/sheet.props.ts index 75aea9c87d82..4cdc3b34e3f6 100644 --- a/packages/sdk-components-react-radix/src/__generated__/sheet.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/sheet.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsSheet: Record = { open: { diff --git a/packages/sdk-components-react-radix/src/__generated__/switch.props.ts b/packages/sdk-components-react-radix/src/__generated__/switch.props.ts index 48abac1ea2bb..b9e61e338ae6 100644 --- a/packages/sdk-components-react-radix/src/__generated__/switch.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/switch.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsSwitch: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react-radix/src/__generated__/tabs.props.ts b/packages/sdk-components-react-radix/src/__generated__/tabs.props.ts index fa9daefa49f6..946263a8a364 100644 --- a/packages/sdk-components-react-radix/src/__generated__/tabs.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/tabs.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsTabs: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react-radix/src/__generated__/tooltip.props.ts b/packages/sdk-components-react-radix/src/__generated__/tooltip.props.ts index d54c3be6846a..0b0c1a419a45 100644 --- a/packages/sdk-components-react-radix/src/__generated__/tooltip.props.ts +++ b/packages/sdk-components-react-radix/src/__generated__/tooltip.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const propsTooltip: Record = { delayDuration: { diff --git a/packages/sdk-components-react-remix/package.json b/packages/sdk-components-react-remix/package.json index a7f037b6757f..a4c80bf487a4 100644 --- a/packages/sdk-components-react-remix/package.json +++ b/packages/sdk-components-react-remix/package.json @@ -49,6 +49,7 @@ "@webstudio-is/form-handlers": "workspace:*", "@webstudio-is/icons": "workspace:*", "@webstudio-is/react-sdk": "workspace:*", + "@webstudio-is/sdk": "workspace:*", "@webstudio-is/sdk-components-react": "workspace:*" }, "devDependencies": { diff --git a/packages/sdk-components-react-remix/src/__generated__/form.props.ts b/packages/sdk-components-react-remix/src/__generated__/form.props.ts index cccbb26fdf04..18539fcc9d11 100644 --- a/packages/sdk-components-react-remix/src/__generated__/form.props.ts +++ b/packages/sdk-components-react-remix/src/__generated__/form.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react-remix/src/__generated__/link.props.ts b/packages/sdk-components-react-remix/src/__generated__/link.props.ts index 7a6b4b27c3c9..48c6b6a65eda 100644 --- a/packages/sdk-components-react-remix/src/__generated__/link.props.ts +++ b/packages/sdk-components-react-remix/src/__generated__/link.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react-remix/src/__generated__/rich-text-link.props.ts b/packages/sdk-components-react-remix/src/__generated__/rich-text-link.props.ts index c835e1183926..ae636d2fc288 100644 --- a/packages/sdk-components-react-remix/src/__generated__/rich-text-link.props.ts +++ b/packages/sdk-components-react-remix/src/__generated__/rich-text-link.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/package.json b/packages/sdk-components-react/package.json index 0fe3cdf9e9fb..71b2bd93429d 100644 --- a/packages/sdk-components-react/package.json +++ b/packages/sdk-components-react/package.json @@ -52,6 +52,7 @@ "@webstudio-is/icons": "workspace:*", "@webstudio-is/image": "workspace:*", "@webstudio-is/react-sdk": "workspace:*", + "@webstudio-is/sdk": "workspace:*", "colord": "^2.9.3", "shallow-equal": "^3.1.0" }, diff --git a/packages/sdk-components-react/src/__generated__/blockquote.props.ts b/packages/sdk-components-react/src/__generated__/blockquote.props.ts index c56dae12d0fd..c07ba397b303 100644 --- a/packages/sdk-components-react/src/__generated__/blockquote.props.ts +++ b/packages/sdk-components-react/src/__generated__/blockquote.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/body.props.ts b/packages/sdk-components-react/src/__generated__/body.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/body.props.ts +++ b/packages/sdk-components-react/src/__generated__/body.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/bold.props.ts b/packages/sdk-components-react/src/__generated__/bold.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/bold.props.ts +++ b/packages/sdk-components-react/src/__generated__/bold.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/box.props.ts b/packages/sdk-components-react/src/__generated__/box.props.ts index 597f2382950e..3f32a503a5d1 100644 --- a/packages/sdk-components-react/src/__generated__/box.props.ts +++ b/packages/sdk-components-react/src/__generated__/box.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/button.props.ts b/packages/sdk-components-react/src/__generated__/button.props.ts index fda2a6e9ac1e..6c8b3e7e12be 100644 --- a/packages/sdk-components-react/src/__generated__/button.props.ts +++ b/packages/sdk-components-react/src/__generated__/button.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/checkbox.props.ts b/packages/sdk-components-react/src/__generated__/checkbox.props.ts index ccb4eec528a2..d47389b31199 100644 --- a/packages/sdk-components-react/src/__generated__/checkbox.props.ts +++ b/packages/sdk-components-react/src/__generated__/checkbox.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/code-text.props.ts b/packages/sdk-components-react/src/__generated__/code-text.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/code-text.props.ts +++ b/packages/sdk-components-react/src/__generated__/code-text.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/form.props.ts b/packages/sdk-components-react/src/__generated__/form.props.ts index 186f1c3b3288..a6b03a65e4f6 100644 --- a/packages/sdk-components-react/src/__generated__/form.props.ts +++ b/packages/sdk-components-react/src/__generated__/form.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/fragment.props.ts b/packages/sdk-components-react/src/__generated__/fragment.props.ts index 10ee115b62d3..6898f60c0edd 100644 --- a/packages/sdk-components-react/src/__generated__/fragment.props.ts +++ b/packages/sdk-components-react/src/__generated__/fragment.props.ts @@ -1,3 +1,3 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = {}; diff --git a/packages/sdk-components-react/src/__generated__/heading.props.ts b/packages/sdk-components-react/src/__generated__/heading.props.ts index 80958e70af82..4c468af777b9 100644 --- a/packages/sdk-components-react/src/__generated__/heading.props.ts +++ b/packages/sdk-components-react/src/__generated__/heading.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/html-embed.props.ts b/packages/sdk-components-react/src/__generated__/html-embed.props.ts index 612a3b015a94..bf1ccaf6133f 100644 --- a/packages/sdk-components-react/src/__generated__/html-embed.props.ts +++ b/packages/sdk-components-react/src/__generated__/html-embed.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { clientOnly: { required: false, control: "boolean", type: "boolean" }, diff --git a/packages/sdk-components-react/src/__generated__/image.props.ts b/packages/sdk-components-react/src/__generated__/image.props.ts index e1970d9ad8b1..fa51831d1b3b 100644 --- a/packages/sdk-components-react/src/__generated__/image.props.ts +++ b/packages/sdk-components-react/src/__generated__/image.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/input.props.ts b/packages/sdk-components-react/src/__generated__/input.props.ts index 414006cdb11f..e228e7109f47 100644 --- a/packages/sdk-components-react/src/__generated__/input.props.ts +++ b/packages/sdk-components-react/src/__generated__/input.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/italic.props.ts b/packages/sdk-components-react/src/__generated__/italic.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/italic.props.ts +++ b/packages/sdk-components-react/src/__generated__/italic.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/label.props.ts b/packages/sdk-components-react/src/__generated__/label.props.ts index 409b571854b0..ae1de580cb0d 100644 --- a/packages/sdk-components-react/src/__generated__/label.props.ts +++ b/packages/sdk-components-react/src/__generated__/label.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/link.props.ts b/packages/sdk-components-react/src/__generated__/link.props.ts index 6a1253c5861f..7023ed9de0bf 100644 --- a/packages/sdk-components-react/src/__generated__/link.props.ts +++ b/packages/sdk-components-react/src/__generated__/link.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/list-item.props.ts b/packages/sdk-components-react/src/__generated__/list-item.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/list-item.props.ts +++ b/packages/sdk-components-react/src/__generated__/list-item.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/list.props.ts b/packages/sdk-components-react/src/__generated__/list.props.ts index 7ecfa40f1fdd..e308f01b1016 100644 --- a/packages/sdk-components-react/src/__generated__/list.props.ts +++ b/packages/sdk-components-react/src/__generated__/list.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/paragraph.props.ts b/packages/sdk-components-react/src/__generated__/paragraph.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/paragraph.props.ts +++ b/packages/sdk-components-react/src/__generated__/paragraph.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/radio-button.props.ts b/packages/sdk-components-react/src/__generated__/radio-button.props.ts index ccb4eec528a2..d47389b31199 100644 --- a/packages/sdk-components-react/src/__generated__/radio-button.props.ts +++ b/packages/sdk-components-react/src/__generated__/radio-button.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/rich-text-link.props.ts b/packages/sdk-components-react/src/__generated__/rich-text-link.props.ts index 6a1253c5861f..7023ed9de0bf 100644 --- a/packages/sdk-components-react/src/__generated__/rich-text-link.props.ts +++ b/packages/sdk-components-react/src/__generated__/rich-text-link.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/separator.props.ts b/packages/sdk-components-react/src/__generated__/separator.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/separator.props.ts +++ b/packages/sdk-components-react/src/__generated__/separator.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/slot.props.ts b/packages/sdk-components-react/src/__generated__/slot.props.ts index 10ee115b62d3..6898f60c0edd 100644 --- a/packages/sdk-components-react/src/__generated__/slot.props.ts +++ b/packages/sdk-components-react/src/__generated__/slot.props.ts @@ -1,3 +1,3 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = {}; diff --git a/packages/sdk-components-react/src/__generated__/span.props.ts b/packages/sdk-components-react/src/__generated__/span.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/span.props.ts +++ b/packages/sdk-components-react/src/__generated__/span.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/subscript.props.ts b/packages/sdk-components-react/src/__generated__/subscript.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/subscript.props.ts +++ b/packages/sdk-components-react/src/__generated__/subscript.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/superscript.props.ts b/packages/sdk-components-react/src/__generated__/superscript.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/superscript.props.ts +++ b/packages/sdk-components-react/src/__generated__/superscript.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/text.props.ts b/packages/sdk-components-react/src/__generated__/text.props.ts index 0ad6eac03ceb..2238eea7de1a 100644 --- a/packages/sdk-components-react/src/__generated__/text.props.ts +++ b/packages/sdk-components-react/src/__generated__/text.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/textarea.props.ts b/packages/sdk-components-react/src/__generated__/textarea.props.ts index b530b43df051..7c504bde3c1f 100644 --- a/packages/sdk-components-react/src/__generated__/textarea.props.ts +++ b/packages/sdk-components-react/src/__generated__/textarea.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/vimeo-play-button.props.ts b/packages/sdk-components-react/src/__generated__/vimeo-play-button.props.ts index fef4cb59b19c..cd594cd29162 100644 --- a/packages/sdk-components-react/src/__generated__/vimeo-play-button.props.ts +++ b/packages/sdk-components-react/src/__generated__/vimeo-play-button.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/vimeo-preview-image.props.ts b/packages/sdk-components-react/src/__generated__/vimeo-preview-image.props.ts index dd2b829c5ab1..69bc45c88bf6 100644 --- a/packages/sdk-components-react/src/__generated__/vimeo-preview-image.props.ts +++ b/packages/sdk-components-react/src/__generated__/vimeo-preview-image.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/vimeo-spinner.props.ts b/packages/sdk-components-react/src/__generated__/vimeo-spinner.props.ts index 0a6893554426..a8aa30555ff8 100644 --- a/packages/sdk-components-react/src/__generated__/vimeo-spinner.props.ts +++ b/packages/sdk-components-react/src/__generated__/vimeo-spinner.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-components-react/src/__generated__/vimeo.props.ts b/packages/sdk-components-react/src/__generated__/vimeo.props.ts index 98770b6f2294..1e0a8230b55f 100644 --- a/packages/sdk-components-react/src/__generated__/vimeo.props.ts +++ b/packages/sdk-components-react/src/__generated__/vimeo.props.ts @@ -1,4 +1,4 @@ -import type { PropMeta } from "@webstudio-is/react-sdk"; +import type { PropMeta } from "@webstudio-is/sdk"; export const props: Record = { about: { required: false, control: "text", type: "string" }, diff --git a/packages/sdk-size-test/package.json b/packages/sdk-size-test/package.json index 9cd673e59ae6..629770c6d1a4 100644 --- a/packages/sdk-size-test/package.json +++ b/packages/sdk-size-test/package.json @@ -15,7 +15,7 @@ }, { "path": "functions/*.js", - "limit": "334 kB", + "limit": "337 kB", "gzip": false } ], diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index ae74815db0ce..641f57460afd 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -9,5 +9,7 @@ export * from "./schema/style-source-selections"; export * from "./schema/styles"; export * from "./schema/deployment"; +export * from "./schema/prop-meta"; + export * from "./instances-utils"; export * from "./scope"; diff --git a/packages/react-sdk/src/prop-meta.ts b/packages/sdk/src/schema/prop-meta.ts similarity index 100% rename from packages/react-sdk/src/prop-meta.ts rename to packages/sdk/src/schema/prop-meta.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b18c4957e85..f18409983566 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1056,9 +1056,9 @@ importers: '@webstudio-is/html-data': specifier: workspace:* version: link:../html-data - '@webstudio-is/react-sdk': + '@webstudio-is/sdk': specifier: workspace:* - version: link:../react-sdk + version: link:../sdk fast-glob: specifier: ^3.2.12 version: 3.2.12 @@ -1080,7 +1080,20 @@ importers: version: 5.2.2 packages/html-data: + dependencies: + '@webstudio-is/sdk': + specifier: workspace:* + version: link:../sdk + html-tags: + specifier: ^3.3.1 + version: 3.3.1 + parse5: + specifier: ^7.1.2 + version: 7.1.2 devDependencies: + '@types/node': + specifier: ^18.11.18 + version: 18.13.0 '@webstudio-is/tsconfig': specifier: workspace:* version: link:../tsconfig @@ -1361,6 +1374,9 @@ importers: '@types/react-dom': specifier: ^18.2.7 version: 18.2.7 + '@webstudio-is/html-data': + specifier: workspace:* + version: link:../html-data '@webstudio-is/jest-config': specifier: workspace:* version: link:../jest-config @@ -1475,6 +1491,9 @@ importers: '@webstudio-is/react-sdk': specifier: workspace:* version: link:../react-sdk + '@webstudio-is/sdk': + specifier: workspace:* + version: link:../sdk colord: specifier: ^2.9.3 version: 2.9.3 @@ -1557,6 +1576,9 @@ importers: '@webstudio-is/react-sdk': specifier: workspace:* version: link:../react-sdk + '@webstudio-is/sdk': + specifier: workspace:* + version: link:../sdk devDependencies: '@storybook/react': specifier: ^7.4.0 @@ -1609,6 +1631,9 @@ importers: '@webstudio-is/react-sdk': specifier: workspace:* version: link:../react-sdk + '@webstudio-is/sdk': + specifier: workspace:* + version: link:../sdk '@webstudio-is/sdk-components-react': specifier: workspace:* version: link:../sdk-components-react @@ -9453,7 +9478,6 @@ packages: /entities@4.4.0: resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} engines: {node: '>=0.12'} - dev: true /env-paths@3.0.0: resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} @@ -13781,6 +13805,12 @@ packages: resolution: {integrity: sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==} dev: true + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.4.0 + dev: false + /parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'}