From fbaf8cd1730a884926957f31aac69f30a7a77710 Mon Sep 17 00:00:00 2001 From: "docs-examples-cross-repo-dispatch[bot]" <318227308+docs-examples-cross-repo-dispatch[bot]@users.noreply.github.com> Date: Wed, 28 Oct 2026 07:59:40 +0000 Subject: [PATCH] chore(docs): update versioned docs examples --- ...ides__getting-started__react-redux__react__example1.tsx.json | 2 +- ...ides__getting-started__react-redux__react__example6.tsx.json | 2 +- ...accessibility__keyboard-shortcuts__angular__example1.ts.json | 2 +- ...essibility__keyboard-shortcuts__javascript__example1.js.json | 2 +- ..._accessibility__keyboard-shortcuts__react__example1.tsx.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/runner/apps/authoring/public/docs-examples/18.1/guides__getting-started__react-redux__react__example1.tsx.json b/runner/apps/authoring/public/docs-examples/18.1/guides__getting-started__react-redux__react__example1.tsx.json index a3d7b0d0a7..4948fb67cf 100644 --- a/runner/apps/authoring/public/docs-examples/18.1/guides__getting-started__react-redux__react__example1.tsx.json +++ b/runner/apps/authoring/public/docs-examples/18.1/guides__getting-started__react-redux__react__example1.tsx.json @@ -1 +1 @@ -{"framework":"react","displayName":"Getting Started ▸ Integration with Redux · Standard example · React (TS)","tier":1,"engine":"sandpack","sandpackTemplate":"react-ts","sandpackEnvironment":"parcel","container":null,"htWrappers":["@handsontable/react-wrapper"],"entry":"/src/main.tsx","htmlEntry":"/index.html","devCommand":null,"buildCommand":"vite build","outputDir":"dist","outputGlob":null,"staticExport":false,"spaMode":false,"port":null,"installCommand":"pnpm install","htCoreRange":"18.1.2","fileCount":5,"assets":[],"skipped":[],"files":{"/package.json":"{\n \"name\": \"handsontable-react-example\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.34.5\",\n \"dependencies\": {\n \"handsontable\": \"18.1.2\",\n \"@handsontable/react-wrapper\": \"18.1.2\",\n \"react\": \"18.x\",\n \"react-dom\": \"18.x\",\n \"vite\": \"^5.4.0\",\n \"@vitejs/plugin-react\": \"^4.0.0\",\n \"redux\": \"5.0.1\",\n \"react-redux\": \"9.3.0\"\n },\n \"scripts\": {\n \"start\": \"vite\",\n \"build\": \"vite build\"\n }\n}","/vite.config.js":"import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\nexport default defineConfig({ plugins: [react()] });","/index.html":"\n\n\n \n \n Handsontable React Example\n \n\n\n
\n \n\n","/src/main.tsx":"import React from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport App from \"./App\";\nconst root = createRoot(document.getElementById(\"example1\"));\nroot.render(React.createElement(App));","/src/App.tsx":"import { useRef, MouseEvent, JSXElementConstructor, Key, ReactElement, ReactNode, ReactPortal } from 'react';\nimport { createStore } from 'redux';\nimport { Provider, useSelector, useDispatch } from 'react-redux';\nimport { HotTable } from '@handsontable/react-wrapper';\nimport { registerAllModules } from 'handsontable/registry';\nimport Handsontable from 'handsontable/base';\n\n// register Handsontable's modules\nregisterAllModules();\n\nconst ExampleComponentContent = () => {\n const hotSettings = useSelector((state: RootState) => state);\n const dispatch = useDispatch();\n const hotTableComponentRef = useRef(null);\n\n const hotData = hotSettings.data;\n const isHotData = Array.isArray(hotData);\n\n const onBeforeHotChange = (changes: (Handsontable.CellChange | null)[]) => {\n dispatch({\n type: 'updateData',\n dataChanges: changes,\n });\n\n return false;\n };\n\n const toggleReadOnly = (event: MouseEvent) => {\n dispatch({\n type: 'updateReadOnly',\n readOnly: (event.target as HTMLInputElement).checked,\n });\n };\n\n return (\n
\n
\n
\n
\n
\n \n
\n
\n\n \n
\n

Redux store dump

\n
\n          {isHotData && (\n            
\n data:\n \n \n {hotData.map((row, i) => (\n \n {row.map(\n (\n cell:\n | string\n | number\n | boolean\n | ReactElement>\n | Iterable\n | ReactPortal\n | null\n | undefined,\n i: Key | null | undefined\n ) => (\n \n )\n )}\n \n ))}\n \n
{cell}
\n
\n )}\n\n \n \n {Object.entries(hotSettings).map(\n ([name, value]) =>\n name !== 'data' && (\n \n \n \n \n )\n )}\n \n
\n {name}:\n {value.toString()}
\n
\n
\n
\n );\n};\n\nconst initialReduxStoreState = {\n data: [\n ['A1', 'B1', 'C1'],\n ['A2', 'B2', 'C2'],\n ['A3', 'B3', 'C3'],\n ['A4', 'B4', 'C4'],\n ['A5', 'B5', 'C5'],\n ],\n colHeaders: true,\n rowHeaders: true,\n readOnly: false,\n height: 'auto',\n licenseKey: 'non-commercial-and-evaluation',\n};\n\nconst updatesReducer = (\n state = initialReduxStoreState,\n action: { type: any; dataChanges: [any, any, any, any][]; readOnly: any }\n) => {\n switch (action.type) {\n case 'updateData':\n const newData = state.data.map((row) => [...row]);\n\n action.dataChanges.forEach(([row, column, oldValue, newValue]) => {\n newData[row][column] = newValue;\n });\n\n return {\n ...state,\n data: newData,\n };\n\n case 'updateReadOnly':\n return {\n ...state,\n readOnly: action.readOnly,\n };\n\n default:\n return state;\n }\n};\n\nexport type RootState = ReturnType;\n\nconst reduxStore = createStore(updatesReducer);\n\nconst ExampleComponent = () => (\n \n \n \n);\n\nexport default ExampleComponent;"},"docsPath":"guides/getting-started/react-redux/react/example1.tsx","breadcrumb":["Getting Started","Integration with Redux"],"guide":"guides/getting-started/react-redux/react-redux.md","guideTitle":"Integration with Redux","exampleId":"example1","exampleTitle":"Standard example","docPermalink":"/redux","lang":"React (TS)"} +{"framework":"react","displayName":"Getting Started ▸ Integration with Redux · Standard example · React (TS)","tier":1,"engine":"sandpack","sandpackTemplate":"react-ts","sandpackEnvironment":"parcel","container":null,"htWrappers":["@handsontable/react-wrapper"],"entry":"/src/main.tsx","htmlEntry":"/index.html","devCommand":null,"buildCommand":"vite build","outputDir":"dist","outputGlob":null,"staticExport":false,"spaMode":false,"port":null,"installCommand":"pnpm install","htCoreRange":"18.1.2","fileCount":5,"assets":[],"skipped":[],"files":{"/package.json":"{\n \"name\": \"handsontable-react-example\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.34.5\",\n \"dependencies\": {\n \"handsontable\": \"18.1.2\",\n \"@handsontable/react-wrapper\": \"18.1.2\",\n \"react\": \"18.x\",\n \"react-dom\": \"18.x\",\n \"vite\": \"^5.4.0\",\n \"@vitejs/plugin-react\": \"^4.0.0\",\n \"redux\": \"5.0.1\",\n \"react-redux\": \"9.3.1\"\n },\n \"scripts\": {\n \"start\": \"vite\",\n \"build\": \"vite build\"\n }\n}","/vite.config.js":"import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\nexport default defineConfig({ plugins: [react()] });","/index.html":"\n\n\n \n \n Handsontable React Example\n \n\n\n
\n \n\n","/src/main.tsx":"import React from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport App from \"./App\";\nconst root = createRoot(document.getElementById(\"example1\"));\nroot.render(React.createElement(App));","/src/App.tsx":"import { useRef, MouseEvent, JSXElementConstructor, Key, ReactElement, ReactNode, ReactPortal } from 'react';\nimport { createStore } from 'redux';\nimport { Provider, useSelector, useDispatch } from 'react-redux';\nimport { HotTable } from '@handsontable/react-wrapper';\nimport { registerAllModules } from 'handsontable/registry';\nimport Handsontable from 'handsontable/base';\n\n// register Handsontable's modules\nregisterAllModules();\n\nconst ExampleComponentContent = () => {\n const hotSettings = useSelector((state: RootState) => state);\n const dispatch = useDispatch();\n const hotTableComponentRef = useRef(null);\n\n const hotData = hotSettings.data;\n const isHotData = Array.isArray(hotData);\n\n const onBeforeHotChange = (changes: (Handsontable.CellChange | null)[]) => {\n dispatch({\n type: 'updateData',\n dataChanges: changes,\n });\n\n return false;\n };\n\n const toggleReadOnly = (event: MouseEvent) => {\n dispatch({\n type: 'updateReadOnly',\n readOnly: (event.target as HTMLInputElement).checked,\n });\n };\n\n return (\n
\n
\n
\n
\n
\n \n
\n
\n\n \n
\n

Redux store dump

\n
\n          {isHotData && (\n            
\n data:\n \n \n {hotData.map((row, i) => (\n \n {row.map(\n (\n cell:\n | string\n | number\n | boolean\n | ReactElement>\n | Iterable\n | ReactPortal\n | null\n | undefined,\n i: Key | null | undefined\n ) => (\n \n )\n )}\n \n ))}\n \n
{cell}
\n
\n )}\n\n \n \n {Object.entries(hotSettings).map(\n ([name, value]) =>\n name !== 'data' && (\n \n \n \n \n )\n )}\n \n
\n {name}:\n {value.toString()}
\n
\n
\n
\n );\n};\n\nconst initialReduxStoreState = {\n data: [\n ['A1', 'B1', 'C1'],\n ['A2', 'B2', 'C2'],\n ['A3', 'B3', 'C3'],\n ['A4', 'B4', 'C4'],\n ['A5', 'B5', 'C5'],\n ],\n colHeaders: true,\n rowHeaders: true,\n readOnly: false,\n height: 'auto',\n licenseKey: 'non-commercial-and-evaluation',\n};\n\nconst updatesReducer = (\n state = initialReduxStoreState,\n action: { type: any; dataChanges: [any, any, any, any][]; readOnly: any }\n) => {\n switch (action.type) {\n case 'updateData':\n const newData = state.data.map((row) => [...row]);\n\n action.dataChanges.forEach(([row, column, oldValue, newValue]) => {\n newData[row][column] = newValue;\n });\n\n return {\n ...state,\n data: newData,\n };\n\n case 'updateReadOnly':\n return {\n ...state,\n readOnly: action.readOnly,\n };\n\n default:\n return state;\n }\n};\n\nexport type RootState = ReturnType;\n\nconst reduxStore = createStore(updatesReducer);\n\nconst ExampleComponent = () => (\n \n \n \n);\n\nexport default ExampleComponent;"},"docsPath":"guides/getting-started/react-redux/react/example1.tsx","breadcrumb":["Getting Started","Integration with Redux"],"guide":"guides/getting-started/react-redux/react-redux.md","guideTitle":"Integration with Redux","exampleId":"example1","exampleTitle":"Standard example","docPermalink":"/redux","lang":"React (TS)"} diff --git a/runner/apps/authoring/public/docs-examples/18.1/guides__getting-started__react-redux__react__example6.tsx.json b/runner/apps/authoring/public/docs-examples/18.1/guides__getting-started__react-redux__react__example6.tsx.json index d8086c9632..308c737a01 100644 --- a/runner/apps/authoring/public/docs-examples/18.1/guides__getting-started__react-redux__react__example6.tsx.json +++ b/runner/apps/authoring/public/docs-examples/18.1/guides__getting-started__react-redux__react__example6.tsx.json @@ -1 +1 @@ -{"framework":"react","displayName":"Getting Started ▸ Integration with Redux · Advanced example · React (TS)","tier":1,"engine":"sandpack","sandpackTemplate":"react-ts","sandpackEnvironment":"parcel","container":null,"htWrappers":["@handsontable/react-wrapper"],"entry":"/src/main.tsx","htmlEntry":"/index.html","devCommand":null,"buildCommand":"vite build","outputDir":"dist","outputGlob":null,"staticExport":false,"spaMode":false,"port":null,"installCommand":"pnpm install","htCoreRange":"18.1.2","fileCount":5,"assets":[],"skipped":[],"files":{"/package.json":"{\n \"name\": \"handsontable-react-example\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.34.5\",\n \"dependencies\": {\n \"handsontable\": \"18.1.2\",\n \"@handsontable/react-wrapper\": \"18.1.2\",\n \"react\": \"18.x\",\n \"react-dom\": \"18.x\",\n \"vite\": \"^5.4.0\",\n \"@vitejs/plugin-react\": \"^4.0.0\",\n \"react-colorful\": \"5.8.1\",\n \"react-redux\": \"9.3.0\",\n \"redux\": \"5.0.1\"\n },\n \"scripts\": {\n \"start\": \"vite\",\n \"build\": \"vite build\"\n }\n}","/vite.config.js":"import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\nexport default defineConfig({ plugins: [react()] });","/index.html":"\n\n\n \n \n Handsontable React Example\n \n\n\n
\n \n\n","/src/main.tsx":"import React from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport App from \"./App\";\nconst root = createRoot(document.getElementById(\"example6\"));\nroot.render(React.createElement(App));","/src/App.tsx":"import { useEffect, MouseEvent, KeyboardEvent, useRef, useState } from 'react';\nimport Handsontable from 'handsontable/base';\nimport { HexColorPicker } from 'react-colorful';\nimport { Provider, connect, useDispatch } from 'react-redux';\nimport { createStore, combineReducers } from 'redux';\nimport { HotTable, HotColumn, useHotEditor } from '@handsontable/react-wrapper';\nimport { registerAllModules } from 'handsontable/registry';\n\n// register Handsontable's modules\nregisterAllModules();\n\ninterface StarRatingProps {\n name: string;\n value?: number;\n starCount?: number;\n starColor?: string;\n emptyStarColor?: string;\n}\n\nfunction StarRating({ name, value = 0, starCount = 5, starColor = '#ffb400', emptyStarColor = '#d3d3d3' }: StarRatingProps) {\n return (\n
\n {Array.from({ length: starCount }, (_, i) => (\n \n ★\n \n ))}\n
\n );\n}\n\ntype RendererProps = {\n TD?: HTMLTableCellElement;\n value?: string | number;\n row?: number;\n col?: number;\n cellProperties?: Handsontable.CellProperties;\n};\n\nconst UnconnectedColorPickerEditor = () => {\n const dispatch = useDispatch();\n const editorRef = useRef(null);\n const [pickedColor, setPickedColor] = useState('');\n\n const { value, setValue, isOpen, finishEditing, col, row } = useHotEditor({\n onOpen: () => {\n if (editorRef.current) editorRef.current.style.display = 'block';\n (document.querySelector('.react-colorful__interactive') as HTMLDivElement)?.focus();\n },\n onClose: () => {\n if (editorRef.current) editorRef.current.style.display = 'none';\n\n setPickedColor('');\n },\n onPrepare: (_row, _column, _prop, TD, _originalValue, _cellProperties) => {\n const tdPosition = TD.getBoundingClientRect();\n\n if (!editorRef.current) return;\n\n editorRef.current.style.left = `${tdPosition.left + window.pageXOffset}px`;\n editorRef.current.style.top = `${tdPosition.top + window.pageYOffset}px`;\n },\n onFocus: () => {},\n });\n\n const onPickedColor = (color: string) => {\n setValue(color);\n };\n\n const applyColor = () => {\n if (col === 1) {\n dispatch({\n type: 'updateActiveStarColor',\n row,\n hexColor: value,\n });\n } else if (col === 2) {\n dispatch({\n type: 'updateInactiveStarColor',\n row,\n hexColor: value,\n });\n }\n\n finishEditing();\n };\n\n const stopMousedownPropagation = (e: MouseEvent) => {\n e.stopPropagation();\n };\n\n const stopKeyboardPropagation = (e: KeyboardEvent) => {\n e.stopPropagation();\n\n if (e.key === 'Escape') {\n applyColor();\n }\n };\n\n return (\n \n \n \n \n );\n};\n\nconst ColorPickerEditor = connect(function (state: RootState) {\n return {\n activeColors: state.appReducer.activeColors,\n inactiveColors: state.appReducer.inactiveColors,\n };\n})(UnconnectedColorPickerEditor);\n\nconst ColorPickerRenderer = ({ value }: RendererProps) => {\n return (\n <>\n \n
{value}
\n \n );\n};\n\n// a Redux component\nconst initialReduxStoreState: {\n activeColors?: string[];\n inactiveColors?: string[];\n} = {\n activeColors: [],\n inactiveColors: [],\n};\n\nconst appReducer = (\n state = initialReduxStoreState,\n action: { type?: any; row?: any; hexColor?: any; hotData?: any }\n) => {\n switch (action.type) {\n case 'initRatingColors': {\n const { hotData } = action;\n\n const activeColors = hotData.map((data: string[]) => data[1]);\n const inactiveColors = hotData.map((data: string[]) => data[2]);\n\n return {\n ...state,\n activeColors,\n inactiveColors,\n };\n }\n\n case 'updateActiveStarColor': {\n const rowIndex = action.row;\n const newColor = action.hexColor;\n\n const activeColorArray = state.activeColors ? [...state.activeColors] : [];\n\n activeColorArray[rowIndex] = newColor;\n\n return {\n ...state,\n activeColors: activeColorArray,\n };\n }\n\n case 'updateInactiveStarColor': {\n const rowIndex = action.row;\n const newColor = action.hexColor;\n\n const inactiveColorArray = state.inactiveColors ? [...state.inactiveColors] : [];\n\n inactiveColorArray[rowIndex] = newColor;\n\n return {\n ...state,\n inactiveColors: inactiveColorArray,\n };\n }\n\n default:\n return state;\n }\n};\n\nconst actionReducers = combineReducers({ appReducer });\nconst reduxStore = createStore(actionReducers);\n\ntype RootState = ReturnType;\n\n// a custom renderer component\nconst UnconnectedStarRatingRenderer = ({\n row,\n col,\n value,\n activeColors,\n inactiveColors,\n}: {\n row?: number;\n col?: number;\n value?: number;\n activeColors?: string;\n inactiveColors?: string;\n}) => {\n return (\n \n );\n};\n\nconst StarRatingRenderer = connect((state: RootState) => ({\n activeColors: state.appReducer.activeColors,\n inactiveColors: state.appReducer.inactiveColors,\n}))(UnconnectedStarRatingRenderer);\n\nconst data = [\n [1, '#ff6900', '#fcb900'],\n [2, '#fcb900', '#7bdcb5'],\n [3, '#7bdcb5', '#8ed1fc'],\n [4, '#00d084', '#0693e3'],\n [5, '#eb144c', '#abb8c3'],\n];\n\nconst ExampleComponent = () => {\n useEffect(() => {\n reduxStore.dispatch({\n type: 'initRatingColors',\n hotData: data,\n });\n }, []);\n\n return (\n \n \n \n \n \n \n \n );\n};\n\nexport default ExampleComponent;"},"docsPath":"guides/getting-started/react-redux/react/example6.tsx","breadcrumb":["Getting Started","Integration with Redux"],"guide":"guides/getting-started/react-redux/react-redux.md","guideTitle":"Integration with Redux","exampleId":"example6","exampleTitle":"Advanced example","docPermalink":"/redux","lang":"React (TS)"} +{"framework":"react","displayName":"Getting Started ▸ Integration with Redux · Advanced example · React (TS)","tier":1,"engine":"sandpack","sandpackTemplate":"react-ts","sandpackEnvironment":"parcel","container":null,"htWrappers":["@handsontable/react-wrapper"],"entry":"/src/main.tsx","htmlEntry":"/index.html","devCommand":null,"buildCommand":"vite build","outputDir":"dist","outputGlob":null,"staticExport":false,"spaMode":false,"port":null,"installCommand":"pnpm install","htCoreRange":"18.1.2","fileCount":5,"assets":[],"skipped":[],"files":{"/package.json":"{\n \"name\": \"handsontable-react-example\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.34.5\",\n \"dependencies\": {\n \"handsontable\": \"18.1.2\",\n \"@handsontable/react-wrapper\": \"18.1.2\",\n \"react\": \"18.x\",\n \"react-dom\": \"18.x\",\n \"vite\": \"^5.4.0\",\n \"@vitejs/plugin-react\": \"^4.0.0\",\n \"react-colorful\": \"5.8.1\",\n \"react-redux\": \"9.3.1\",\n \"redux\": \"5.0.1\"\n },\n \"scripts\": {\n \"start\": \"vite\",\n \"build\": \"vite build\"\n }\n}","/vite.config.js":"import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\nexport default defineConfig({ plugins: [react()] });","/index.html":"\n\n\n \n \n Handsontable React Example\n \n\n\n
\n \n\n","/src/main.tsx":"import React from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport App from \"./App\";\nconst root = createRoot(document.getElementById(\"example6\"));\nroot.render(React.createElement(App));","/src/App.tsx":"import { useEffect, MouseEvent, KeyboardEvent, useRef, useState } from 'react';\nimport Handsontable from 'handsontable/base';\nimport { HexColorPicker } from 'react-colorful';\nimport { Provider, connect, useDispatch } from 'react-redux';\nimport { createStore, combineReducers } from 'redux';\nimport { HotTable, HotColumn, useHotEditor } from '@handsontable/react-wrapper';\nimport { registerAllModules } from 'handsontable/registry';\n\n// register Handsontable's modules\nregisterAllModules();\n\ninterface StarRatingProps {\n name: string;\n value?: number;\n starCount?: number;\n starColor?: string;\n emptyStarColor?: string;\n}\n\nfunction StarRating({ name, value = 0, starCount = 5, starColor = '#ffb400', emptyStarColor = '#d3d3d3' }: StarRatingProps) {\n return (\n
\n {Array.from({ length: starCount }, (_, i) => (\n \n ★\n \n ))}\n
\n );\n}\n\ntype RendererProps = {\n TD?: HTMLTableCellElement;\n value?: string | number;\n row?: number;\n col?: number;\n cellProperties?: Handsontable.CellProperties;\n};\n\nconst UnconnectedColorPickerEditor = () => {\n const dispatch = useDispatch();\n const editorRef = useRef(null);\n const [pickedColor, setPickedColor] = useState('');\n\n const { value, setValue, isOpen, finishEditing, col, row } = useHotEditor({\n onOpen: () => {\n if (editorRef.current) editorRef.current.style.display = 'block';\n (document.querySelector('.react-colorful__interactive') as HTMLDivElement)?.focus();\n },\n onClose: () => {\n if (editorRef.current) editorRef.current.style.display = 'none';\n\n setPickedColor('');\n },\n onPrepare: (_row, _column, _prop, TD, _originalValue, _cellProperties) => {\n const tdPosition = TD.getBoundingClientRect();\n\n if (!editorRef.current) return;\n\n editorRef.current.style.left = `${tdPosition.left + window.pageXOffset}px`;\n editorRef.current.style.top = `${tdPosition.top + window.pageYOffset}px`;\n },\n onFocus: () => {},\n });\n\n const onPickedColor = (color: string) => {\n setValue(color);\n };\n\n const applyColor = () => {\n if (col === 1) {\n dispatch({\n type: 'updateActiveStarColor',\n row,\n hexColor: value,\n });\n } else if (col === 2) {\n dispatch({\n type: 'updateInactiveStarColor',\n row,\n hexColor: value,\n });\n }\n\n finishEditing();\n };\n\n const stopMousedownPropagation = (e: MouseEvent) => {\n e.stopPropagation();\n };\n\n const stopKeyboardPropagation = (e: KeyboardEvent) => {\n e.stopPropagation();\n\n if (e.key === 'Escape') {\n applyColor();\n }\n };\n\n return (\n \n \n \n \n );\n};\n\nconst ColorPickerEditor = connect(function (state: RootState) {\n return {\n activeColors: state.appReducer.activeColors,\n inactiveColors: state.appReducer.inactiveColors,\n };\n})(UnconnectedColorPickerEditor);\n\nconst ColorPickerRenderer = ({ value }: RendererProps) => {\n return (\n <>\n \n
{value}
\n \n );\n};\n\n// a Redux component\nconst initialReduxStoreState: {\n activeColors?: string[];\n inactiveColors?: string[];\n} = {\n activeColors: [],\n inactiveColors: [],\n};\n\nconst appReducer = (\n state = initialReduxStoreState,\n action: { type?: any; row?: any; hexColor?: any; hotData?: any }\n) => {\n switch (action.type) {\n case 'initRatingColors': {\n const { hotData } = action;\n\n const activeColors = hotData.map((data: string[]) => data[1]);\n const inactiveColors = hotData.map((data: string[]) => data[2]);\n\n return {\n ...state,\n activeColors,\n inactiveColors,\n };\n }\n\n case 'updateActiveStarColor': {\n const rowIndex = action.row;\n const newColor = action.hexColor;\n\n const activeColorArray = state.activeColors ? [...state.activeColors] : [];\n\n activeColorArray[rowIndex] = newColor;\n\n return {\n ...state,\n activeColors: activeColorArray,\n };\n }\n\n case 'updateInactiveStarColor': {\n const rowIndex = action.row;\n const newColor = action.hexColor;\n\n const inactiveColorArray = state.inactiveColors ? [...state.inactiveColors] : [];\n\n inactiveColorArray[rowIndex] = newColor;\n\n return {\n ...state,\n inactiveColors: inactiveColorArray,\n };\n }\n\n default:\n return state;\n }\n};\n\nconst actionReducers = combineReducers({ appReducer });\nconst reduxStore = createStore(actionReducers);\n\ntype RootState = ReturnType;\n\n// a custom renderer component\nconst UnconnectedStarRatingRenderer = ({\n row,\n col,\n value,\n activeColors,\n inactiveColors,\n}: {\n row?: number;\n col?: number;\n value?: number;\n activeColors?: string;\n inactiveColors?: string;\n}) => {\n return (\n \n );\n};\n\nconst StarRatingRenderer = connect((state: RootState) => ({\n activeColors: state.appReducer.activeColors,\n inactiveColors: state.appReducer.inactiveColors,\n}))(UnconnectedStarRatingRenderer);\n\nconst data = [\n [1, '#ff6900', '#fcb900'],\n [2, '#fcb900', '#7bdcb5'],\n [3, '#7bdcb5', '#8ed1fc'],\n [4, '#00d084', '#0693e3'],\n [5, '#eb144c', '#abb8c3'],\n];\n\nconst ExampleComponent = () => {\n useEffect(() => {\n reduxStore.dispatch({\n type: 'initRatingColors',\n hotData: data,\n });\n }, []);\n\n return (\n \n \n \n \n \n \n \n );\n};\n\nexport default ExampleComponent;"},"docsPath":"guides/getting-started/react-redux/react/example6.tsx","breadcrumb":["Getting Started","Integration with Redux"],"guide":"guides/getting-started/react-redux/react-redux.md","guideTitle":"Integration with Redux","exampleId":"example6","exampleTitle":"Advanced example","docPermalink":"/redux","lang":"React (TS)"} diff --git a/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__angular__example1.ts.json b/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__angular__example1.ts.json index 0b607212b4..1666d36946 100644 --- a/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__angular__example1.ts.json +++ b/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__angular__example1.ts.json @@ -1 +1 @@ -{"framework":"angular","displayName":"Recipes ▸ Accessibility ▸ Custom keyboard shortcuts · Standard example · Angular","tier":2,"engine":"container","sandpackTemplate":null,"sandpackEnvironment":null,"container":"angular","htWrappers":["@handsontable/angular-wrapper"],"entry":"/src/main.ts","htmlEntry":"/src/index.html","devCommand":"pnpm exec ng serve --host 0.0.0.0 --port 3000","buildCommand":"ng build","outputDir":"dist","outputGlob":"dist/*/browser","staticExport":false,"spaMode":false,"port":3000,"installCommand":"pnpm install","htCoreRange":"18.1.2","fileCount":7,"assets":[],"skipped":[],"files":{"/package.json":"{\n \"name\": \"handsontable-angular-example\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.34.5\",\n \"scripts\": {\n \"ng\": \"ng\",\n \"start\": \"ng serve\",\n \"build\": \"ng build\"\n },\n \"dependencies\": {\n \"handsontable\": \"18.1.2\",\n \"@handsontable/angular-wrapper\": \"18.1.2\",\n \"@angular/animations\": \"22.0.6\",\n \"@angular/common\": \"22.0.6\",\n \"@angular/compiler\": \"22.0.6\",\n \"@angular/core\": \"22.0.6\",\n \"@angular/forms\": \"22.0.6\",\n \"@angular/platform-browser\": \"22.0.6\",\n \"@angular/platform-browser-dynamic\": \"22.0.6\",\n \"@angular/router\": \"22.0.6\",\n \"rxjs\": \"~7.8.2\",\n \"tslib\": \"^2.8.1\",\n \"zone.js\": \"~0.16.2\",\n \"@angular-devkit/build-angular\": \"22.0.6\",\n \"@angular/cli\": \"22.0.6\",\n \"@angular/compiler-cli\": \"22.0.6\",\n \"typescript\": \"~6.0.3\"\n },\n \"devDependencies\": {}\n}","/angular.json":"{\n \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n \"version\": 1,\n \"newProjectRoot\": \"projects\",\n \"projects\": {\n \"app\": {\n \"projectType\": \"application\",\n \"root\": \"\",\n \"sourceRoot\": \"src\",\n \"prefix\": \"app\",\n \"architect\": {\n \"build\": {\n \"builder\": \"@angular-devkit/build-angular:application\",\n \"options\": {\n \"outputPath\": \"dist/app\",\n \"index\": \"src/index.html\",\n \"browser\": \"src/main.ts\",\n \"polyfills\": [\n \"zone.js\"\n ],\n \"tsConfig\": \"tsconfig.json\",\n \"assets\": [],\n \"styles\": [],\n \"scripts\": []\n },\n \"configurations\": {\n \"development\": {\n \"optimization\": false,\n \"sourceMap\": true\n }\n },\n \"defaultConfiguration\": \"development\"\n },\n \"serve\": {\n \"builder\": \"@angular-devkit/build-angular:dev-server\",\n \"configurations\": {\n \"development\": {\n \"buildTarget\": \"app:build:development\"\n }\n },\n \"defaultConfiguration\": \"development\"\n }\n }\n }\n }\n}","/tsconfig.json":"{\n \"compilerOptions\": {\n \"outDir\": \"./dist/out-tsc\",\n \"strict\": true,\n \"noImplicitOverride\": true,\n \"noPropertyAccessFromIndexSignature\": true,\n \"noImplicitReturns\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"skipLibCheck\": true,\n \"esModuleInterop\": true,\n \"sourceMap\": true,\n \"declaration\": false,\n \"experimentalDecorators\": true,\n \"moduleResolution\": \"bundler\",\n \"importHelpers\": true,\n \"target\": \"ES2022\",\n \"module\": \"ES2022\",\n \"useDefineForClassFields\": false,\n \"lib\": [\n \"ES2022\",\n \"dom\"\n ]\n },\n \"angularCompilerOptions\": {\n \"enableI18nLegacyMessageIdFormat\": false,\n \"strictInjectionParameters\": true,\n \"strictInputAccessModifiers\": true,\n \"strictTemplates\": true\n }\n}","/src/index.html":"\n\n\n \n Handsontable Angular Example\n \n \n\n\n
\n \n
\n\n","/src/main.ts":"import { bootstrapApplication } from '@angular/platform-browser';\nimport { registerAllModules } from 'handsontable/registry';\nimport { AppComponent } from './app/app.component';\nimport { appConfig } from './app/app.config';\n\nregisterAllModules();\n\nbootstrapApplication(AppComponent, appConfig).catch(err => console.error(err));","/src/app/app.component.ts":"import { Component, ViewChild, AfterViewInit, OnDestroy, NgZone, inject } from '@angular/core';\nimport { GridSettings, HotTableComponent, HotTableModule } from '@handsontable/angular-wrapper';\n\n/* start:skip-in-preview */\nconst employees = [\n { name: 'Ana García', department: 'Engineering', role: 'Senior Developer', salary: 95000, startDate: '2021-03-15' },\n { name: 'James Okafor', department: 'Marketing', role: 'Marketing Manager', salary: 82000, startDate: '2020-07-01' },\n { name: 'Li Wei', department: 'Engineering', role: 'Frontend Developer', salary: 78000, startDate: '2022-01-10' },\n { name: 'Priya Nair', department: 'HR', role: 'HR Specialist', salary: 68000, startDate: '2019-11-20' },\n { name: 'Carlos Mendes', department: 'Finance', role: 'Financial Analyst', salary: 88000, startDate: '2021-09-05' },\n { name: 'Fatima Al-Hassan', department: 'Engineering', role: 'Backend Developer', salary: 92000, startDate: '2020-04-18' },\n { name: 'Noah Kim', department: 'Design', role: 'UX Designer', salary: 75000, startDate: '2023-02-14' },\n { name: 'Sara Lindqvist', department: 'Marketing', role: 'Content Strategist', salary: 71000, startDate: '2019-06-30' },\n];\n/* end:skip-in-preview */\n\n@Component({\n selector: 'example1-keyboard-shortcuts',\n standalone: true,\n imports: [HotTableModule],\n template: `\n \n Shortcut log:\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Last shortcut triggered{{ lastShortcut }}
Last submission{{ lastSubmission }}
\n `,\n})\nexport class AppComponent implements AfterViewInit, OnDestroy {\n @ViewChild(HotTableComponent, { static: false }) readonly hotTable!: HotTableComponent;\n\n private readonly ngZone = inject(NgZone);\n\n data = employees;\n lastShortcut = '—';\n lastSubmission = '—';\n\n readonly gridSettings: GridSettings = {\n colHeaders: ['Name', 'Department', 'Role', 'Salary', 'Start Date'],\n columns: [\n { data: 'name', type: 'text' },\n { data: 'department', type: 'text' },\n { data: 'role', type: 'text' },\n { data: 'salary', type: 'numeric', locale: 'en-US', numericFormat: { style: 'currency', currency: 'USD', minimumFractionDigits: 0, maximumFractionDigits: 0 } },\n { data: 'startDate', type: 'text' },\n ],\n rowHeaders: true,\n height: 'auto',\n width: '100%',\n autoWrapRow: true,\n };\n\n ngAfterViewInit(): void {\n const hot = this.hotTable?.hotInstance;\n\n if (!hot) {\n return;\n }\n\n const gridContext = hot.getShortcutManager().getContext('grid');\n\n if (!gridContext) {\n return;\n }\n\n // Ctrl+D: duplicate the currently selected row\n gridContext.addShortcut({\n keys: [['Control', 'd']],\n group: 'customActions',\n runOnlyIf: () => hot.getSelected() !== undefined,\n callback: (event: Event) => {\n event.preventDefault();\n\n const selectedRange = hot.getSelectedRangeLast();\n\n if (!selectedRange) {\n return;\n }\n\n const row = selectedRange.from.row;\n\n if (row === null) {\n return;\n }\n\n const rowData = hot.getSourceDataAtRow(row) as Record;\n\n hot.alter('insert_row_below', row);\n hot.populateFromArray(row + 1, 0, [Object.values(rowData)]);\n\n this.ngZone.run(() => { this.lastShortcut = 'Ctrl+D -- row duplicated'; });\n },\n });\n\n // Ctrl+Enter: submit the grid data\n gridContext.addShortcut({\n keys: [['Control', 'Enter']],\n group: 'customActions',\n runOnlyIf: () => true,\n callback: (event: Event) => {\n event.preventDefault();\n\n const data = hot.getData();\n const headers = hot.getColHeader() as string[];\n const rowCount = data.length;\n const timestamp = new Date().toLocaleTimeString();\n\n this.ngZone.run(() => {\n this.lastShortcut = 'Ctrl+Enter -- data submitted';\n this.lastSubmission = `[${timestamp}] Submitted ${rowCount} rows -- columns: ${headers.join(', ')}`;\n });\n },\n });\n }\n\n ngOnDestroy(): void {\n const hot = this.hotTable?.hotInstance;\n\n if (!hot) {\n return;\n }\n\n hot.getShortcutManager().getContext('grid')?.removeShortcutsByGroup('customActions');\n }\n}","/src/app/app.config.ts":"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';\nimport { registerAllModules } from 'handsontable/registry';\nimport { HOT_GLOBAL_CONFIG, HotGlobalConfig, NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';\n\nregisterAllModules();\n\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideZoneChangeDetection({ eventCoalescing: true }),\n {\n provide: HOT_GLOBAL_CONFIG,\n useValue: { license: NON_COMMERCIAL_LICENSE } as HotGlobalConfig,\n },\n ],\n};"},"docsPath":"recipes/accessibility/keyboard-shortcuts/angular/example1.ts","breadcrumb":["Recipes","Accessibility","Custom keyboard shortcuts"],"guide":"recipes/accessibility/keyboard-shortcuts/keyboard-shortcuts.md","guideTitle":"Custom keyboard shortcuts","exampleId":"example1","exampleTitle":"Standard example","docPermalink":"/recipes/accessibility/keyboard-shortcuts","lang":"Angular"} +{"framework":"angular","displayName":"Recipes ▸ Accessibility ▸ Custom keyboard shortcuts · Standard example · Angular","tier":2,"engine":"container","sandpackTemplate":null,"sandpackEnvironment":null,"container":"angular","htWrappers":["@handsontable/angular-wrapper"],"entry":"/src/main.ts","htmlEntry":"/src/index.html","devCommand":"pnpm exec ng serve --host 0.0.0.0 --port 3000","buildCommand":"ng build","outputDir":"dist","outputGlob":"dist/*/browser","staticExport":false,"spaMode":false,"port":3000,"installCommand":"pnpm install","htCoreRange":"18.1.2","fileCount":7,"assets":[],"skipped":[],"files":{"/package.json":"{\n \"name\": \"handsontable-angular-example\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.34.5\",\n \"scripts\": {\n \"ng\": \"ng\",\n \"start\": \"ng serve\",\n \"build\": \"ng build\"\n },\n \"dependencies\": {\n \"handsontable\": \"18.1.2\",\n \"@handsontable/angular-wrapper\": \"18.1.2\",\n \"@angular/animations\": \"22.0.6\",\n \"@angular/common\": \"22.0.6\",\n \"@angular/compiler\": \"22.0.6\",\n \"@angular/core\": \"22.0.6\",\n \"@angular/forms\": \"22.0.6\",\n \"@angular/platform-browser\": \"22.0.6\",\n \"@angular/platform-browser-dynamic\": \"22.0.6\",\n \"@angular/router\": \"22.0.6\",\n \"rxjs\": \"~7.8.2\",\n \"tslib\": \"^2.8.1\",\n \"zone.js\": \"~0.16.2\",\n \"@angular-devkit/build-angular\": \"22.0.6\",\n \"@angular/cli\": \"22.0.6\",\n \"@angular/compiler-cli\": \"22.0.6\",\n \"typescript\": \"~6.0.3\"\n },\n \"devDependencies\": {}\n}","/angular.json":"{\n \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n \"version\": 1,\n \"newProjectRoot\": \"projects\",\n \"projects\": {\n \"app\": {\n \"projectType\": \"application\",\n \"root\": \"\",\n \"sourceRoot\": \"src\",\n \"prefix\": \"app\",\n \"architect\": {\n \"build\": {\n \"builder\": \"@angular-devkit/build-angular:application\",\n \"options\": {\n \"outputPath\": \"dist/app\",\n \"index\": \"src/index.html\",\n \"browser\": \"src/main.ts\",\n \"polyfills\": [\n \"zone.js\"\n ],\n \"tsConfig\": \"tsconfig.json\",\n \"assets\": [],\n \"styles\": [],\n \"scripts\": []\n },\n \"configurations\": {\n \"development\": {\n \"optimization\": false,\n \"sourceMap\": true\n }\n },\n \"defaultConfiguration\": \"development\"\n },\n \"serve\": {\n \"builder\": \"@angular-devkit/build-angular:dev-server\",\n \"configurations\": {\n \"development\": {\n \"buildTarget\": \"app:build:development\"\n }\n },\n \"defaultConfiguration\": \"development\"\n }\n }\n }\n }\n}","/tsconfig.json":"{\n \"compilerOptions\": {\n \"outDir\": \"./dist/out-tsc\",\n \"strict\": true,\n \"noImplicitOverride\": true,\n \"noPropertyAccessFromIndexSignature\": true,\n \"noImplicitReturns\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"skipLibCheck\": true,\n \"esModuleInterop\": true,\n \"sourceMap\": true,\n \"declaration\": false,\n \"experimentalDecorators\": true,\n \"moduleResolution\": \"bundler\",\n \"importHelpers\": true,\n \"target\": \"ES2022\",\n \"module\": \"ES2022\",\n \"useDefineForClassFields\": false,\n \"lib\": [\n \"ES2022\",\n \"dom\"\n ]\n },\n \"angularCompilerOptions\": {\n \"enableI18nLegacyMessageIdFormat\": false,\n \"strictInjectionParameters\": true,\n \"strictInputAccessModifiers\": true,\n \"strictTemplates\": true\n }\n}","/src/index.html":"\n\n\n \n Handsontable Angular Example\n \n \n\n\n
\n \n
\n\n","/src/main.ts":"import { bootstrapApplication } from '@angular/platform-browser';\nimport { registerAllModules } from 'handsontable/registry';\nimport { AppComponent } from './app/app.component';\nimport { appConfig } from './app/app.config';\n\nregisterAllModules();\n\nbootstrapApplication(AppComponent, appConfig).catch(err => console.error(err));","/src/app/app.component.ts":"import { Component, ViewChild, AfterViewInit, OnDestroy, NgZone, inject } from '@angular/core';\nimport { GridSettings, HotTableComponent, HotTableModule } from '@handsontable/angular-wrapper';\n\n/* start:skip-in-preview */\nconst employees = [\n { name: 'Ana García', department: 'Engineering', role: 'Senior Developer', salary: 95000, startDate: '2021-03-15' },\n { name: 'James Okafor', department: 'Marketing', role: 'Marketing Manager', salary: 82000, startDate: '2020-07-01' },\n { name: 'Li Wei', department: 'Engineering', role: 'Frontend Developer', salary: 78000, startDate: '2022-01-10' },\n { name: 'Priya Nair', department: 'HR', role: 'HR Specialist', salary: 68000, startDate: '2019-11-20' },\n { name: 'Carlos Mendes', department: 'Finance', role: 'Financial Analyst', salary: 88000, startDate: '2021-09-05' },\n { name: 'Fatima Al-Hassan', department: 'Engineering', role: 'Backend Developer', salary: 92000, startDate: '2020-04-18' },\n { name: 'Noah Kim', department: 'Design', role: 'UX Designer', salary: 75000, startDate: '2023-02-14' },\n { name: 'Sara Lindqvist', department: 'Marketing', role: 'Content Strategist', salary: 71000, startDate: '2019-06-30' },\n];\n/* end:skip-in-preview */\n\n@Component({\n selector: 'example1-keyboard-shortcuts',\n standalone: true,\n imports: [HotTableModule],\n template: `\n \n Shortcut log:\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Last shortcut triggered{{ lastShortcut }}
Last submission{{ lastSubmission }}
\n `,\n})\nexport class AppComponent implements AfterViewInit, OnDestroy {\n @ViewChild(HotTableComponent, { static: false }) readonly hotTable!: HotTableComponent;\n\n private readonly ngZone = inject(NgZone);\n\n data = employees;\n lastShortcut = '—';\n lastSubmission = '—';\n\n readonly gridSettings: GridSettings = {\n colHeaders: ['Name', 'Department', 'Role', 'Salary', 'Start Date'],\n columns: [\n { data: 'name', type: 'text' },\n { data: 'department', type: 'text' },\n { data: 'role', type: 'text' },\n { data: 'salary', type: 'numeric', locale: 'en-US', numericFormat: { style: 'currency', currency: 'USD', minimumFractionDigits: 0, maximumFractionDigits: 0 } },\n { data: 'startDate', type: 'text' },\n ],\n rowHeaders: true,\n height: 'auto',\n width: '100%',\n autoWrapRow: true,\n };\n\n ngAfterViewInit(): void {\n const hot = this.hotTable?.hotInstance;\n\n if (!hot) {\n return;\n }\n\n const gridContext = hot.getShortcutManager().getContext('grid');\n\n if (!gridContext) {\n return;\n }\n\n // Ctrl+D: duplicate the currently selected row\n gridContext.addShortcut({\n keys: [['Control', 'd']],\n group: 'customActions',\n runOnlyIf: () => hot.getSelected() !== undefined,\n callback: (event: Event) => {\n event.preventDefault();\n\n const selectedRange = hot.getSelectedRangeLast();\n\n if (!selectedRange) {\n return;\n }\n\n const row = selectedRange.from.row;\n\n if (row === null) {\n return;\n }\n\n const rowData = hot.getSourceDataAtRow(row) as Record;\n\n hot.alter('insert_row_below', row);\n hot.populateFromArray(row + 1, 0, [Object.values(rowData)]);\n\n this.ngZone.run(() => { this.lastShortcut = 'Ctrl+D -- row duplicated'; });\n },\n });\n\n // Ctrl+Shift+Enter: submit the grid data\n gridContext.addShortcut({\n keys: [['Control', 'Shift', 'Enter']],\n group: 'customActions',\n runOnlyIf: () => true,\n callback: (event: Event) => {\n event.preventDefault();\n\n const data = hot.getData();\n const headers = hot.getColHeader() as string[];\n const rowCount = data.length;\n const timestamp = new Date().toLocaleTimeString();\n\n this.ngZone.run(() => {\n this.lastShortcut = 'Ctrl+Shift+Enter -- data submitted';\n this.lastSubmission = `[${timestamp}] Submitted ${rowCount} rows -- columns: ${headers.join(', ')}`;\n });\n },\n });\n }\n\n ngOnDestroy(): void {\n const hot = this.hotTable?.hotInstance;\n\n if (!hot) {\n return;\n }\n\n hot.getShortcutManager().getContext('grid')?.removeShortcutsByGroup('customActions');\n }\n}","/src/app/app.config.ts":"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';\nimport { registerAllModules } from 'handsontable/registry';\nimport { HOT_GLOBAL_CONFIG, HotGlobalConfig, NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';\n\nregisterAllModules();\n\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideZoneChangeDetection({ eventCoalescing: true }),\n {\n provide: HOT_GLOBAL_CONFIG,\n useValue: { license: NON_COMMERCIAL_LICENSE } as HotGlobalConfig,\n },\n ],\n};"},"docsPath":"recipes/accessibility/keyboard-shortcuts/angular/example1.ts","breadcrumb":["Recipes","Accessibility","Custom keyboard shortcuts"],"guide":"recipes/accessibility/keyboard-shortcuts/keyboard-shortcuts.md","guideTitle":"Custom keyboard shortcuts","exampleId":"example1","exampleTitle":"Standard example","docPermalink":"/recipes/accessibility/keyboard-shortcuts","lang":"Angular"} diff --git a/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__javascript__example1.js.json b/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__javascript__example1.js.json index 446825e247..21a064a7e2 100644 --- a/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__javascript__example1.js.json +++ b/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__javascript__example1.js.json @@ -1 +1 @@ -{"framework":"javascript","displayName":"Recipes ▸ Accessibility ▸ Custom keyboard shortcuts · Standard example · JavaScript","tier":1,"engine":"sandpack","sandpackTemplate":"vanilla","sandpackEnvironment":"parcel","container":null,"htWrappers":[],"entry":"/src/main.js","htmlEntry":"/index.html","devCommand":null,"buildCommand":"vite build","outputDir":"dist","outputGlob":null,"staticExport":false,"spaMode":false,"port":null,"installCommand":"pnpm install","htCoreRange":"18.1.2","fileCount":4,"assets":[],"skipped":[],"files":{"/package.json":"{\n \"name\": \"handsontable-example\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.34.5\",\n \"dependencies\": {\n \"handsontable\": \"18.1.2\",\n \"vite\": \"^5.4.0\"\n },\n \"scripts\": {\n \"start\": \"vite\",\n \"build\": \"vite build\"\n }\n}","/index.html":"\n\n\n \n \n Handsontable Example\n \n\n\n
\n Shortcut log:\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Last shortcut triggered—
Last submission—
\n \n\n","/index.js":"import Handsontable from 'handsontable/base';\nimport { registerAllModules } from 'handsontable/registry';\n\nregisterAllModules();\n\n/* start:skip-in-preview */\nconst employees = [\n { name: 'Ana García', department: 'Engineering', role: 'Senior Developer', salary: 95000, startDate: '2021-03-15' },\n { name: 'James Okafor', department: 'Marketing', role: 'Marketing Manager', salary: 82000, startDate: '2020-07-01' },\n { name: 'Li Wei', department: 'Engineering', role: 'Frontend Developer', salary: 78000, startDate: '2022-01-10' },\n { name: 'Priya Nair', department: 'HR', role: 'HR Specialist', salary: 68000, startDate: '2019-11-20' },\n { name: 'Carlos Mendes', department: 'Finance', role: 'Financial Analyst', salary: 88000, startDate: '2021-09-05' },\n { name: 'Fatima Al-Hassan', department: 'Engineering', role: 'Backend Developer', salary: 92000, startDate: '2020-04-18' },\n { name: 'Noah Kim', department: 'Design', role: 'UX Designer', salary: 75000, startDate: '2023-02-14' },\n { name: 'Sara Lindqvist', department: 'Marketing', role: 'Content Strategist', salary: 71000, startDate: '2019-06-30' },\n];\n/* end:skip-in-preview */\n\nconst container = document.querySelector('#example1');\n\nconst hot = new Handsontable(container, {\n data: employees,\n colHeaders: ['Name', 'Department', 'Role', 'Salary', 'Start Date'],\n columns: [\n { data: 'name', type: 'text' },\n { data: 'department', type: 'text' },\n { data: 'role', type: 'text' },\n { data: 'salary', type: 'numeric', locale: 'en-US', numericFormat: { style: 'currency', currency: 'USD', minimumFractionDigits: 0, maximumFractionDigits: 0 } },\n { data: 'startDate', type: 'text' },\n ],\n rowHeaders: true,\n height: 'auto',\n width: '100%',\n autoWrapRow: true,\n licenseKey: 'non-commercial-and-evaluation',\n});\n\nconst preview = container.closest('.hot-example-preview') ?? container.parentElement;\nconst lastShortcutEl = preview.querySelector('.last-shortcut');\nconst lastSubmissionEl = preview.querySelector('.last-submission');\n\nconst gridContext = hot.getShortcutManager().getContext('grid');\n\n// Ctrl+D: duplicate the currently selected row\ngridContext.addShortcut({\n keys: [['Control', 'd']],\n group: 'customActions',\n runOnlyIf: () => hot.getSelected() !== undefined,\n callback: (event) => {\n event.preventDefault();\n\n const selectedRange = hot.getSelectedRangeLast();\n\n if (!selectedRange) {\n return;\n }\n\n const row = selectedRange.from.row;\n const rowData = hot.getSourceDataAtRow(row);\n\n hot.alter('insert_row_below', row);\n hot.populateFromArray(row + 1, 0, [Object.values(rowData)]);\n\n lastShortcutEl.textContent = 'Ctrl+D -- row duplicated';\n },\n});\n\n// Ctrl+Enter: submit the grid data\ngridContext.addShortcut({\n keys: [['Control', 'Enter']],\n group: 'customActions',\n runOnlyIf: () => true,\n callback: (event) => {\n event.preventDefault();\n\n const data = hot.getData();\n const headers = hot.getColHeader();\n const rowCount = data.length;\n const timestamp = new Date().toLocaleTimeString();\n\n lastShortcutEl.textContent = 'Ctrl+Enter -- data submitted';\n lastSubmissionEl.textContent = `[${timestamp}] Submitted ${rowCount} rows -- columns: ${headers.join(', ')}`;\n },\n});","/src/main.js":"import \"../index.js\";"},"docsPath":"recipes/accessibility/keyboard-shortcuts/javascript/example1.js","breadcrumb":["Recipes","Accessibility","Custom keyboard shortcuts"],"guide":"recipes/accessibility/keyboard-shortcuts/keyboard-shortcuts.md","guideTitle":"Custom keyboard shortcuts","exampleId":"example1","exampleTitle":"Standard example","docPermalink":"/recipes/accessibility/keyboard-shortcuts","lang":"JavaScript"} +{"framework":"javascript","displayName":"Recipes ▸ Accessibility ▸ Custom keyboard shortcuts · Standard example · JavaScript","tier":1,"engine":"sandpack","sandpackTemplate":"vanilla","sandpackEnvironment":"parcel","container":null,"htWrappers":[],"entry":"/src/main.js","htmlEntry":"/index.html","devCommand":null,"buildCommand":"vite build","outputDir":"dist","outputGlob":null,"staticExport":false,"spaMode":false,"port":null,"installCommand":"pnpm install","htCoreRange":"18.1.2","fileCount":4,"assets":[],"skipped":[],"files":{"/package.json":"{\n \"name\": \"handsontable-example\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.34.5\",\n \"dependencies\": {\n \"handsontable\": \"18.1.2\",\n \"vite\": \"^5.4.0\"\n },\n \"scripts\": {\n \"start\": \"vite\",\n \"build\": \"vite build\"\n }\n}","/index.html":"\n\n\n \n \n Handsontable Example\n \n\n\n
\n Shortcut log:\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Last shortcut triggered—
Last submission—
\n \n\n","/index.js":"import Handsontable from 'handsontable/base';\nimport { registerAllModules } from 'handsontable/registry';\n\nregisterAllModules();\n\n/* start:skip-in-preview */\nconst employees = [\n { name: 'Ana García', department: 'Engineering', role: 'Senior Developer', salary: 95000, startDate: '2021-03-15' },\n { name: 'James Okafor', department: 'Marketing', role: 'Marketing Manager', salary: 82000, startDate: '2020-07-01' },\n { name: 'Li Wei', department: 'Engineering', role: 'Frontend Developer', salary: 78000, startDate: '2022-01-10' },\n { name: 'Priya Nair', department: 'HR', role: 'HR Specialist', salary: 68000, startDate: '2019-11-20' },\n { name: 'Carlos Mendes', department: 'Finance', role: 'Financial Analyst', salary: 88000, startDate: '2021-09-05' },\n { name: 'Fatima Al-Hassan', department: 'Engineering', role: 'Backend Developer', salary: 92000, startDate: '2020-04-18' },\n { name: 'Noah Kim', department: 'Design', role: 'UX Designer', salary: 75000, startDate: '2023-02-14' },\n { name: 'Sara Lindqvist', department: 'Marketing', role: 'Content Strategist', salary: 71000, startDate: '2019-06-30' },\n];\n/* end:skip-in-preview */\n\nconst container = document.querySelector('#example1');\n\nconst hot = new Handsontable(container, {\n data: employees,\n colHeaders: ['Name', 'Department', 'Role', 'Salary', 'Start Date'],\n columns: [\n { data: 'name', type: 'text' },\n { data: 'department', type: 'text' },\n { data: 'role', type: 'text' },\n { data: 'salary', type: 'numeric', locale: 'en-US', numericFormat: { style: 'currency', currency: 'USD', minimumFractionDigits: 0, maximumFractionDigits: 0 } },\n { data: 'startDate', type: 'text' },\n ],\n rowHeaders: true,\n height: 'auto',\n width: '100%',\n autoWrapRow: true,\n licenseKey: 'non-commercial-and-evaluation',\n});\n\nconst preview = container.closest('.hot-example-preview') ?? container.parentElement;\nconst lastShortcutEl = preview.querySelector('.last-shortcut');\nconst lastSubmissionEl = preview.querySelector('.last-submission');\n\nconst gridContext = hot.getShortcutManager().getContext('grid');\n\n// Ctrl+D: duplicate the currently selected row\ngridContext.addShortcut({\n keys: [['Control', 'd']],\n group: 'customActions',\n runOnlyIf: () => hot.getSelected() !== undefined,\n callback: (event) => {\n event.preventDefault();\n\n const selectedRange = hot.getSelectedRangeLast();\n\n if (!selectedRange) {\n return;\n }\n\n const row = selectedRange.from.row;\n const rowData = hot.getSourceDataAtRow(row);\n\n hot.alter('insert_row_below', row);\n hot.populateFromArray(row + 1, 0, [Object.values(rowData)]);\n\n lastShortcutEl.textContent = 'Ctrl+D -- row duplicated';\n },\n});\n\n// Ctrl+Shift+Enter: submit the grid data\ngridContext.addShortcut({\n keys: [['Control', 'Shift', 'Enter']],\n group: 'customActions',\n runOnlyIf: () => true,\n callback: (event) => {\n event.preventDefault();\n\n const data = hot.getData();\n const headers = hot.getColHeader();\n const rowCount = data.length;\n const timestamp = new Date().toLocaleTimeString();\n\n lastShortcutEl.textContent = 'Ctrl+Shift+Enter -- data submitted';\n lastSubmissionEl.textContent = `[${timestamp}] Submitted ${rowCount} rows -- columns: ${headers.join(', ')}`;\n },\n});","/src/main.js":"import \"../index.js\";"},"docsPath":"recipes/accessibility/keyboard-shortcuts/javascript/example1.js","breadcrumb":["Recipes","Accessibility","Custom keyboard shortcuts"],"guide":"recipes/accessibility/keyboard-shortcuts/keyboard-shortcuts.md","guideTitle":"Custom keyboard shortcuts","exampleId":"example1","exampleTitle":"Standard example","docPermalink":"/recipes/accessibility/keyboard-shortcuts","lang":"JavaScript"} diff --git a/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__react__example1.tsx.json b/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__react__example1.tsx.json index 508dac3d17..191eacac25 100644 --- a/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__react__example1.tsx.json +++ b/runner/apps/authoring/public/docs-examples/18.1/recipes__accessibility__keyboard-shortcuts__react__example1.tsx.json @@ -1 +1 @@ -{"framework":"react","displayName":"Recipes ▸ Accessibility ▸ Custom keyboard shortcuts · Standard example · React (TS)","tier":1,"engine":"sandpack","sandpackTemplate":"react-ts","sandpackEnvironment":"parcel","container":null,"htWrappers":["@handsontable/react-wrapper"],"entry":"/src/main.tsx","htmlEntry":"/index.html","devCommand":null,"buildCommand":"vite build","outputDir":"dist","outputGlob":null,"staticExport":false,"spaMode":false,"port":null,"installCommand":"pnpm install","htCoreRange":"18.1.2","fileCount":5,"assets":[],"skipped":[],"files":{"/package.json":"{\n \"name\": \"handsontable-react-example\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.34.5\",\n \"dependencies\": {\n \"handsontable\": \"18.1.2\",\n \"@handsontable/react-wrapper\": \"18.1.2\",\n \"react\": \"18.x\",\n \"react-dom\": \"18.x\",\n \"vite\": \"^5.4.0\",\n \"@vitejs/plugin-react\": \"^4.0.0\"\n },\n \"scripts\": {\n \"start\": \"vite\",\n \"build\": \"vite build\"\n }\n}","/vite.config.js":"import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\nexport default defineConfig({ plugins: [react()] });","/index.html":"\n\n\n \n \n Handsontable React Example\n \n\n\n
\n \n\n","/src/main.tsx":"import React from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport App from \"./App\";\nconst root = createRoot(document.getElementById(\"example1\"));\nroot.render(React.createElement(App));","/src/App.tsx":"import { useRef, useState, useEffect } from 'react';\nimport { HotTable } from '@handsontable/react-wrapper';\nimport { registerAllModules } from 'handsontable/registry';\nimport type Handsontable from 'handsontable/base';\n\nregisterAllModules();\n\n/* start:skip-in-preview */\nconst employees = [\n { name: 'Ana García', department: 'Engineering', role: 'Senior Developer', salary: 95000, startDate: '2021-03-15' },\n { name: 'James Okafor', department: 'Marketing', role: 'Marketing Manager', salary: 82000, startDate: '2020-07-01' },\n { name: 'Li Wei', department: 'Engineering', role: 'Frontend Developer', salary: 78000, startDate: '2022-01-10' },\n { name: 'Priya Nair', department: 'HR', role: 'HR Specialist', salary: 68000, startDate: '2019-11-20' },\n { name: 'Carlos Mendes', department: 'Finance', role: 'Financial Analyst', salary: 88000, startDate: '2021-09-05' },\n { name: 'Fatima Al-Hassan', department: 'Engineering', role: 'Backend Developer', salary: 92000, startDate: '2020-04-18' },\n { name: 'Noah Kim', department: 'Design', role: 'UX Designer', salary: 75000, startDate: '2023-02-14' },\n { name: 'Sara Lindqvist', department: 'Marketing', role: 'Content Strategist', salary: 71000, startDate: '2019-06-30' },\n];\n/* end:skip-in-preview */\n\nconst ExampleComponent = () => {\n const hotRef = useRef<{ hotInstance: Handsontable | null } | null>(null);\n const [lastShortcut, setLastShortcut] = useState('—');\n const [lastSubmission, setLastSubmission] = useState('—');\n\n useEffect(() => {\n const hot = hotRef.current?.hotInstance;\n\n if (!hot) {\n return;\n }\n\n const gridContext = hot.getShortcutManager().getContext('grid');\n\n // Ctrl+D: duplicate the currently selected row\n gridContext.addShortcut({\n keys: [['Control', 'd']],\n group: 'customActions',\n runOnlyIf: () => hot.getSelected() !== undefined,\n callback: (event: KeyboardEvent) => {\n event.preventDefault();\n\n const selectedRange = hot.getSelectedRangeLast();\n\n if (!selectedRange) {\n return;\n }\n\n const row = selectedRange.from.row;\n const rowData = hot.getSourceDataAtRow(row) as Record;\n\n hot.alter('insert_row_below', row);\n hot.populateFromArray(row + 1, 0, [Object.values(rowData)]);\n\n setLastShortcut('Ctrl+D -- row duplicated');\n },\n });\n\n // Ctrl+Enter: submit the grid data\n gridContext.addShortcut({\n keys: [['Control', 'Enter']],\n group: 'customActions',\n runOnlyIf: () => true,\n callback: (event: KeyboardEvent) => {\n event.preventDefault();\n\n const data = hot.getData();\n const headers = hot.getColHeader() as string[];\n const rowCount = data.length;\n const timestamp = new Date().toLocaleTimeString();\n\n setLastShortcut('Ctrl+Enter -- data submitted');\n setLastSubmission(`[${timestamp}] Submitted ${rowCount} rows -- columns: ${headers.join(', ')}`);\n },\n });\n\n return () => {\n gridContext.removeShortcutsByGroup('customActions');\n };\n }, []);\n\n return (\n <>\n \n Shortcut log:\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Last shortcut triggered{lastShortcut}
Last submission{lastSubmission}
\n \n );\n};\n\nexport default ExampleComponent;"},"docsPath":"recipes/accessibility/keyboard-shortcuts/react/example1.tsx","breadcrumb":["Recipes","Accessibility","Custom keyboard shortcuts"],"guide":"recipes/accessibility/keyboard-shortcuts/keyboard-shortcuts.md","guideTitle":"Custom keyboard shortcuts","exampleId":"example1","exampleTitle":"Standard example","docPermalink":"/recipes/accessibility/keyboard-shortcuts","lang":"React (TS)"} +{"framework":"react","displayName":"Recipes ▸ Accessibility ▸ Custom keyboard shortcuts · Standard example · React (TS)","tier":1,"engine":"sandpack","sandpackTemplate":"react-ts","sandpackEnvironment":"parcel","container":null,"htWrappers":["@handsontable/react-wrapper"],"entry":"/src/main.tsx","htmlEntry":"/index.html","devCommand":null,"buildCommand":"vite build","outputDir":"dist","outputGlob":null,"staticExport":false,"spaMode":false,"port":null,"installCommand":"pnpm install","htCoreRange":"18.1.2","fileCount":5,"assets":[],"skipped":[],"files":{"/package.json":"{\n \"name\": \"handsontable-react-example\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.34.5\",\n \"dependencies\": {\n \"handsontable\": \"18.1.2\",\n \"@handsontable/react-wrapper\": \"18.1.2\",\n \"react\": \"18.x\",\n \"react-dom\": \"18.x\",\n \"vite\": \"^5.4.0\",\n \"@vitejs/plugin-react\": \"^4.0.0\"\n },\n \"scripts\": {\n \"start\": \"vite\",\n \"build\": \"vite build\"\n }\n}","/vite.config.js":"import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\nexport default defineConfig({ plugins: [react()] });","/index.html":"\n\n\n \n \n Handsontable React Example\n \n\n\n
\n \n\n","/src/main.tsx":"import React from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport App from \"./App\";\nconst root = createRoot(document.getElementById(\"example1\"));\nroot.render(React.createElement(App));","/src/App.tsx":"import { useRef, useState, useEffect } from 'react';\nimport { HotTable } from '@handsontable/react-wrapper';\nimport { registerAllModules } from 'handsontable/registry';\nimport type Handsontable from 'handsontable/base';\n\nregisterAllModules();\n\n/* start:skip-in-preview */\nconst employees = [\n { name: 'Ana García', department: 'Engineering', role: 'Senior Developer', salary: 95000, startDate: '2021-03-15' },\n { name: 'James Okafor', department: 'Marketing', role: 'Marketing Manager', salary: 82000, startDate: '2020-07-01' },\n { name: 'Li Wei', department: 'Engineering', role: 'Frontend Developer', salary: 78000, startDate: '2022-01-10' },\n { name: 'Priya Nair', department: 'HR', role: 'HR Specialist', salary: 68000, startDate: '2019-11-20' },\n { name: 'Carlos Mendes', department: 'Finance', role: 'Financial Analyst', salary: 88000, startDate: '2021-09-05' },\n { name: 'Fatima Al-Hassan', department: 'Engineering', role: 'Backend Developer', salary: 92000, startDate: '2020-04-18' },\n { name: 'Noah Kim', department: 'Design', role: 'UX Designer', salary: 75000, startDate: '2023-02-14' },\n { name: 'Sara Lindqvist', department: 'Marketing', role: 'Content Strategist', salary: 71000, startDate: '2019-06-30' },\n];\n/* end:skip-in-preview */\n\nconst ExampleComponent = () => {\n const hotRef = useRef<{ hotInstance: Handsontable | null } | null>(null);\n const [lastShortcut, setLastShortcut] = useState('—');\n const [lastSubmission, setLastSubmission] = useState('—');\n\n useEffect(() => {\n const hot = hotRef.current?.hotInstance;\n\n if (!hot) {\n return;\n }\n\n const gridContext = hot.getShortcutManager().getContext('grid');\n\n // Ctrl+D: duplicate the currently selected row\n gridContext.addShortcut({\n keys: [['Control', 'd']],\n group: 'customActions',\n runOnlyIf: () => hot.getSelected() !== undefined,\n callback: (event: KeyboardEvent) => {\n event.preventDefault();\n\n const selectedRange = hot.getSelectedRangeLast();\n\n if (!selectedRange) {\n return;\n }\n\n const row = selectedRange.from.row;\n const rowData = hot.getSourceDataAtRow(row) as Record;\n\n hot.alter('insert_row_below', row);\n hot.populateFromArray(row + 1, 0, [Object.values(rowData)]);\n\n setLastShortcut('Ctrl+D -- row duplicated');\n },\n });\n\n // Ctrl+Shift+Enter: submit the grid data\n gridContext.addShortcut({\n keys: [['Control', 'Shift', 'Enter']],\n group: 'customActions',\n runOnlyIf: () => true,\n callback: (event: KeyboardEvent) => {\n event.preventDefault();\n\n const data = hot.getData();\n const headers = hot.getColHeader() as string[];\n const rowCount = data.length;\n const timestamp = new Date().toLocaleTimeString();\n\n setLastShortcut('Ctrl+Shift+Enter -- data submitted');\n setLastSubmission(`[${timestamp}] Submitted ${rowCount} rows -- columns: ${headers.join(', ')}`);\n },\n });\n\n return () => {\n gridContext.removeShortcutsByGroup('customActions');\n };\n }, []);\n\n return (\n <>\n \n Shortcut log:\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Last shortcut triggered{lastShortcut}
Last submission{lastSubmission}
\n \n );\n};\n\nexport default ExampleComponent;"},"docsPath":"recipes/accessibility/keyboard-shortcuts/react/example1.tsx","breadcrumb":["Recipes","Accessibility","Custom keyboard shortcuts"],"guide":"recipes/accessibility/keyboard-shortcuts/keyboard-shortcuts.md","guideTitle":"Custom keyboard shortcuts","exampleId":"example1","exampleTitle":"Standard example","docPermalink":"/recipes/accessibility/keyboard-shortcuts","lang":"React (TS)"}