UNPKG

tldraw

Version:

A tiny little drawing editor.

177 lines (176 loc) • 6.6 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var A11y_exports = {}; __export(A11y_exports, { DefaultA11yAnnouncer: () => DefaultA11yAnnouncer, SkipToMainContent: () => SkipToMainContent, generateShapeAnnouncementMessage: () => generateShapeAnnouncementMessage, useSelectedShapesAnnouncer: () => useSelectedShapesAnnouncer }); module.exports = __toCommonJS(A11y_exports); var import_jsx_runtime = require("react/jsx-runtime"); var import_editor = require("@tldraw/editor"); var import_react = require("react"); var import_a11y = require("../context/a11y"); var import_useTranslation = require("../hooks/useTranslation/useTranslation"); var import_TldrawUiButton = require("./primitives/Button/TldrawUiButton"); function SkipToMainContent() { const editor = (0, import_editor.useEditor)(); const msg = (0, import_useTranslation.useTranslation)(); const button = (0, import_react.useRef)(null); const handleNavigateToFirstShape = (0, import_react.useCallback)( (e) => { editor.markEventAsHandled(e); button.current?.blur(); const shapes = editor.getCurrentPageShapesInReadingOrder(); if (!shapes.length) return; editor.setSelectedShapes([shapes[0].id]); editor.zoomToSelectionIfOffscreen(256, { animation: { duration: editor.options.animationMediumMs }, inset: 0 }); editor.timers.setTimeout(() => editor.getContainer().focus(), 100); }, [editor] ); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_TldrawUiButton.TldrawUiButton, { ref: button, type: "low", tabIndex: 0, className: "tl-skip-to-main-content", onClick: handleNavigateToFirstShape, children: msg("a11y.skip-to-main-content") } ); } const DefaultA11yAnnouncer = (0, import_react.memo)(function TldrawUiA11yAnnouncer() { const a11y = (0, import_a11y.useA11y)(); const translation = (0, import_useTranslation.useTranslation)(); const msg = (0, import_editor.useValue)("a11y-msg", () => a11y.currentMsg.get(), []); useA11yDebug(msg.msg); useSelectedShapesAnnouncer(); return msg.msg && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { "aria-label": translation("a11y.status"), "aria-live": msg.priority || "assertive", role: "status", "aria-hidden": "false", style: { position: "absolute", top: "-10000px", left: "-10000px" }, children: msg.msg } ); }); function generateShapeAnnouncementMessage(args) { const { editor, selectedShapeIds, msg } = args; let a11yLive = ""; const numShapes = selectedShapeIds.length; if (numShapes > 1) { a11yLive = msg("a11y.multiple-shapes").replace("{num}", numShapes.toString()); } else if (numShapes === 1) { const shapeId = selectedShapeIds[0]; const shape = editor.getShape(shapeId); if (!shape) return ""; const shapeUtil = editor.getShapeUtil(shape.type); const isMedia = ["image", "video"].includes(shape.type); let shapeType = ""; if (shape.type === "geo") { shapeType = msg(`geo-style.${shape.props.geo}`); } else if (isMedia) { shapeType = msg(`a11y.shape-${shape.type}`); } else { shapeType = msg(`tool.${shape.type}`); } const readingOrderShapes = editor.getCurrentPageShapesInReadingOrder(); const currentShapeIndex = (readingOrderShapes.findIndex((s) => s.id === shapeId) + 1).toString(); const totalShapes = readingOrderShapes.length.toString(); const shapeIndex = msg("a11y.shape-index").replace("{num}", currentShapeIndex).replace("{total}", totalShapes); const describingText = shapeUtil.getAriaDescriptor(shape) || shapeUtil.getText(shape) || ""; a11yLive = (describingText ? `${describingText}, ` : "") + `${shapeType}. ${shapeIndex}`; } return a11yLive; } const useSelectedShapesAnnouncer = () => { const editor = (0, import_editor.useMaybeEditor)(); const a11y = (0, import_a11y.useA11y)(); const msg = (0, import_useTranslation.useTranslation)(); const rPrevSelectedShapeIds = (0, import_react.useRef)([]); (0, import_editor.useReactor)( "announce selection", () => { if (!editor) return; const isInSelecting = editor.isIn("select.idle"); if (isInSelecting) { const selectedShapeIds = editor.getSelectedShapeIds(); if (selectedShapeIds !== rPrevSelectedShapeIds.current) { rPrevSelectedShapeIds.current = selectedShapeIds; (0, import_editor.unsafe__withoutCapture)(() => { const a11yLive = generateShapeAnnouncementMessage({ editor, selectedShapeIds, msg }); if (a11yLive) { a11y.announce({ msg: a11yLive }); } }); } } }, [editor, a11y, msg] ); }; const useA11yDebug = (msg) => { const container = (0, import_editor.useContainer)(); (0, import_react.useEffect)(() => { if (import_editor.debugFlags.a11y.get()) { const log = (msg2) => { console.debug( `%ca11y%c: ${msg2}`, `color: white; background: #40C057; padding: 2px;border-radius: 3px;`, "font-weight: normal" ); }; const handleKeyUp = (e) => { const el = document.activeElement; if (e.key === "Tab" && el && el !== document.body && !el.classList.contains("tl-container")) { const label = el.getAttribute("aria-label") || el.getAttribute("title") || el.textContent; if (label) { log(label); } } }; if (msg) { log(msg); } document.addEventListener("keyup", handleKeyUp); return () => document.removeEventListener("keyup", handleKeyUp); } return void 0; }, [container, msg]); }; //# sourceMappingURL=A11y.js.map