/**
* Centralized data attributes used across the Blok editor.
* This is the single source of truth for all data-blok-* attributes.
*
* Access via Blok.DATA_ATTR
*
* AUTO-GENERATED from `src/components/constants/data-attributes.ts` by
* `scripts/generate-data-attributes-dts.mjs`. Do NOT edit by hand — re-run the
* script. Kept self-contained (no `../src` re-export) so consumers' `tsc` never
* pulls raw implementation source into their program. Enforced by
* `test/unit/architecture/published-types-no-src-refs.test.ts`.
*/
export const DATA_ATTR: {
// Core Element Identifiers
/** Interface type identifier (blok, inline-toolbar, tooltip) */
readonly interface: 'data-blok-interface';
/** Block element wrapper */
readonly element: 'data-blok-element';
/** Block element content wrapper */
readonly elementContent: 'data-blok-element-content';
/** Editor wrapper container */
readonly editor: 'data-blok-editor';
/** Per-instance discriminator on the editor wrapper (a monotonic counter, as a
* string). Two editors on one page share every other scope attribute, so this
* is what lets a page-level stylesheet — Blok's own injected `style.fontSize`
* sheet, or a host rule — address ONE editor. Public styling hook. */
readonly instance: 'data-blok-instance';
/** Redactor zone */
readonly redactor: 'data-blok-redactor';
/** Present on the editor wrapper once a `blocks.render()` batch has finished
* inserting blocks into the DOM; removed while a re-render is in flight.
* Acts as a stable render-readiness gate for consumers (e.g. E2E waits). */
readonly rendered: 'data-blok-rendered';
/** Blok version number stamped on the editor wrapper (e.g. '1.10.0', 'dev').
* Consumed by browser extensions to identify the running version. */
readonly version: 'data-blok-version';
// Block Identifiers
/** Block unique identifier */
readonly id: 'data-blok-id';
/** Block component/tool type */
readonly component: 'data-blok-component';
/** Tool type attribute */
readonly tool: 'data-blok-tool';
/** Block nesting depth (derived from the parentId chain) */
readonly depth: 'data-blok-depth';
/** Flat list-nesting indentation level (0 = root); tool-agnostic, mirrors list depth */
readonly indent: 'data-blok-indent';
/** Header tool's heading level (1-6). Public styling hook — keyed by level rather
* than by tag name, so a level remapped to a custom tag via `levelOverrides[n].tag`
* (types/tools/header.d.ts) still matches its level's typography rules. */
readonly headingLevel: 'data-blok-heading-level';
// Global States
/** Element is hidden from view */
readonly hidden: 'data-blok-hidden';
/** Element is disabled and non-interactive */
readonly disabled: 'data-blok-disabled';
/** Element is focused via keyboard navigation */
readonly focused: 'data-blok-focused';
/** Block is selected */
readonly selected: 'data-blok-selected';
/** Block is stretched */
readonly stretched: 'data-blok-stretched';
/** Editor or element is empty */
readonly empty: 'data-blok-empty';
/** Present on the editor wrapper while read-only mode is active.
* Public styling hook — lets hosts key rules off the editing state
* without JS. Deliberately does NOT collapse the gutter: plain
* read-only still shows the block-hover copy-link control there, and
* in-place readOnly.set() flips must not shift the layout. */
readonly readonly: 'data-blok-readonly';
/** Present on the editor wrapper while read-only mode hides ALL editor
* controls (readOnly: { hideControls: true }). Public styling hook —
* drives the gutter auto-collapse for genuinely chromeless read-only. */
readonly controlsHidden: 'data-blok-controls-hidden';
/** Present on the editor wrapper when config.hideToolbar is true.
* Public styling hook — drives the gutter auto-collapse (the gutter
* exists solely to house the toolbar's +/⠿ controls). */
readonly toolbarHidden: 'data-blok-toolbar-hidden';
/** Which gutter the floating block controls occupy: 'left' (default,
* inline-start) or 'right' (inline-end). Written on the editor wrapper from
* config.toolbarPosition and kept in sync by `toolbar.setPosition()`.
* Public styling hook — drives the gutter swap and the actions-bar side. */
readonly toolbarPosition: 'data-blok-toolbar-position';
// Editor Modes
/** Content alignment mode (left, center, right) */
readonly contentAlign: 'data-blok-content-align';
/** Right-to-left mode */
readonly rtl: 'data-blok-rtl';
/** Editor content width mode (present with value "full" for wide mode; absent = narrow) */
readonly width: 'data-blok-width';
/** Present on the editor wrapper when config.style.nativeSelection is true.
* Public styling hook — disables Blok's ::selection repaint (preflight.css)
* and re-points the fake-background highlight at the UA Highlight color
* (colors.css), so selection falls back to native/host-defined colors. */
readonly nativeSelection: 'data-blok-native-selection';
/** Present on the editor wrapper while a cross-block TEXT selection is painted.
* Suppresses the engine's own ::selection paint (main.css) so the
* ::highlight() sub-ranges are the only thing drawn — Chromium and Firefox
* paint such a range natively too and would otherwise double it up. */
readonly crossSelection: 'data-blok-cross-selection';
// Drag and Drop
/** Block is being dragged */
readonly dragging: 'data-blok-dragging';
/** Multiple blocks being dragged */
readonly draggingMulti: 'data-blok-dragging-multi';
/** Block is being duplicated (Alt+drag) */
readonly duplicating: 'data-blok-duplicating';
/** Drag handle element */
readonly dragHandle: 'data-blok-drag-handle';
// Toolbar
/** Toolbar element */
readonly toolbar: 'data-blok-toolbar';
/** The floating block-controls bar (plus button + drag/settings handle)
* inside the toolbar. Public styling hook — the side it docks to is driven
* from the wrapper's `data-blok-toolbar-position`. */
readonly toolbarActions: 'data-blok-toolbar-actions';
/** Settings toggler button */
readonly settingsToggler: 'data-blok-settings-toggler';
/** Toolbox is open */
readonly toolboxOpened: 'data-blok-toolbox-opened';
/** Block settings is open */
readonly blockSettingsOpened: 'data-blok-block-settings-opened';
/** Element is opened (generic) */
readonly opened: 'data-blok-opened';
// Popover Container
/** Root popover element */
readonly popover: 'data-blok-popover';
/** Popover container wrapper */
readonly popoverContainer: 'data-blok-popover-container';
/** Popover items list */
readonly popoverItems: 'data-blok-popover-items';
/** Custom, engine-independent scrollbar thumb overlaid on the popover items */
readonly popoverScrollbar: 'data-blok-popover-scrollbar';
/** Stamped on the custom scrollbar thumb while it is being dragged (keeps it revealed) */
readonly popoverScrollbarDragging: 'data-blok-dragging';
/** Stamped on a scroll container while it is actively scrolling (reveals the auto-hidden scrollbar thumb) */
readonly scrolling: 'data-blok-scrolling';
/** Popover overlay element */
readonly popoverOverlay: 'data-blok-popover-overlay';
/** Popover custom content area */
readonly popoverCustomContent: 'data-blok-popover-custom-content';
/** Popover custom class */
readonly popoverCustomClass: 'data-blok-popover-custom-class';
/** Inline popover variant */
readonly popoverInline: 'data-blok-popover-inline';
/** Popover is open */
readonly popoverOpened: 'data-blok-popover-opened';
/** Popover opens upward */
readonly popoverOpenTop: 'data-blok-popover-open-top';
/** Popover opens leftward */
readonly popoverOpenLeft: 'data-blok-popover-open-left';
// Popover Nesting
/** Nested popover indicator */
readonly nested: 'data-blok-nested';
/** Nesting level value */
readonly nestedLevel: 'data-blok-nested-level';
/** Group label for promoted search results from nested children */
readonly promotedGroupLabel: 'data-blok-promoted-group-label';
/** Group label for top-level matches in search results */
readonly topLevelGroupLabel: 'data-blok-top-level-group-label';
// Popover Header
/** Header container */
readonly popoverHeader: 'data-blok-popover-header';
/** Header text element */
readonly popoverHeaderText: 'data-blok-popover-header-text';
/** Back button in nested popover */
readonly popoverHeaderBackButton: 'data-blok-popover-header-back-button';
// Popover Items
/** Item container */
readonly popoverItem: 'data-blok-popover-item';
/** Item icon wrapper */
readonly popoverItemIcon: 'data-blok-popover-item-icon';
/** Chevron icon for nested items */
readonly popoverItemIconChevronRight: 'data-blok-popover-item-icon-chevron-right';
/** Item title text */
readonly popoverItemTitle: 'data-blok-popover-item-title';
/** Item secondary title */
readonly popoverItemSecondaryTitle: 'data-blok-popover-item-secondary-title';
/** Item is active/selected */
readonly popoverItemActive: 'data-blok-popover-item-active';
/** Item's child menu is currently open — keeps the trigger looking selected */
readonly popoverItemChildrenOpen: 'data-blok-popover-item-children-open';
/** Confirmation state */
readonly popoverItemConfirmation: 'data-blok-popover-item-confirmation';
/** Disable hover styling */
readonly popoverItemNoHover: 'data-blok-popover-item-no-hover';
/** Disable focus handling */
readonly popoverItemNoFocus: 'data-blok-popover-item-no-focus';
/** Destructive action item (e.g. delete) */
readonly popoverItemDestructive: 'data-blok-popover-item-destructive';
/** Separator item */
readonly popoverItemSeparator: 'data-blok-popover-item-separator';
/** Separator line element */
readonly popoverItemSeparatorLine: 'data-blok-popover-item-separator-line';
/** HTML-based item */
readonly popoverItemHtml: 'data-blok-popover-item-html';
/** Item has child menu */
readonly hasChildren: 'data-blok-has-children';
/** Item name identifier */
readonly itemName: 'data-blok-item-name';
/** No search results shown */
readonly nothingFoundDisplayed: 'data-blok-nothing-found-displayed';
// Overlay / Selection
/** Selection overlay */
readonly overlay: 'data-blok-overlay';
/** Overlay container */
readonly overlayContainer: 'data-blok-overlay-container';
/** Selection rectangle */
readonly overlayRectangle: 'data-blok-overlay-rectangle';
/** Overlay is hidden */
readonly overlayHidden: 'data-blok-overlay-hidden';
/** Fake cursor indicator */
readonly fakeCursor: 'data-blok-fake-cursor';
/** Fake background for selection */
readonly fakeBackground: 'data-blok-fake-background';
// Scroll
/** Auto-scroll zone (top/bottom) */
readonly scrollZone: 'data-blok-scroll-zone';
/** Scroll is locked */
readonly scrollLocked: 'data-blok-scroll-locked';
/** Hard scroll lock */
readonly scrollLockedHard: 'data-blok-scroll-locked-hard';
// Caret
/** Shadow caret element */
readonly shadowCaret: 'data-blok-shadow-caret';
// Placeholders
/** Placeholder text */
readonly placeholder: 'data-blok-placeholder';
/** Active placeholder text */
readonly placeholderActive: 'data-blok-placeholder-active';
// Columns Layout
/** The columns row rendered by the column_list tool (the flex container).
* Public styling hook — its direct `[data-blok-element]` children are the
* column holders, whose shrink floor reads `--blok-column-min-width` and
* whose gutter reads `--blok-column-gutter`. */
readonly columns: 'data-blok-columns';
/** A single column inside a columns row. */
readonly column: 'data-blok-column';
/** Drag-to-resize separator between two adjacent columns. Present only in
* edit mode — the separators ARE the gutter there. */
readonly columnResizer: 'data-blok-column-resizer';
/** Present on a columns row whose gutter comes from the container's own
* column-gap instead of from resizer elements. Set in read-only mode, where
* no resizers are built — the discriminator between an editable row and a
* published one. */
readonly columnsStaticGutter: 'data-blok-columns-static-gutter';
// Nested Blocks
/** Container that hosts nested block holders (table cells, toggle/callout/header children).
* Used as a universal guard: before moving a block holder via appendChild,
* check `holder.closest([nestedBlocks])` — if truthy, the holder is already
* claimed by another container and must not be stolen. */
readonly nestedBlocks: 'data-blok-nested-blocks';
// Mutation Tracking
/** Element excluded from mutation tracking */
readonly mutationFree: 'data-blok-mutation-free';
// Keyboard Ownership
/** Marks a subtree whose keyboard belongs to the Tool that rendered it, not to
* the editor. Blok's block-level keydown/keyup handling stands down entirely
* for events originating inside it — Escape, Tab, the arrows, "/" and the
* Enter/Backspace/Delete structural keys all reach the element untouched.
*
* Blok already exempts native ``/`