From 692a4e4b767308b91ce1882662ec3b33e9ad1151 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Wed, 11 Sep 2024 15:06:17 +0200 Subject: [PATCH 01/41] WIP: Get rid of the vueoress build errors --- docs/.vuepress/components/ScriptLoader.vue | 39 +++ docs/.vuepress/config.js | 2 + .../plugins/examples/add-code-for-preset.js | 53 ++++ .../plugins/examples/code-builder.js | 32 +++ .../buildAngularBody.js | 233 ++++++++++++++++ .../buildJavascriptBody.js | 92 ++++++ .../code-structure-builder/buildReactBody.js | 207 ++++++++++++++ .../code-structure-builder/buildVue3Body.js | 67 +++++ .../code-structure-builder/buildVueBody.js | 76 +++++ .../code-structure-builder/getBody.js | 42 +++ docs/.vuepress/plugins/examples/examples.js | 247 ++++++++++++++++ docs/.vuepress/plugins/examples/stackblitz.js | 53 ++++ docs/examples/demo/example1.css | 5 + docs/examples/demo/example1.html | 2 + docs/examples/demo/example1.js | 4 + docs/examples/demo/example1.ts | 4 + docs/guide/demo.md | 23 +- package-lock.json | 263 +++++++++++++++--- package.json | 9 + 19 files changed, 1400 insertions(+), 53 deletions(-) create mode 100644 docs/.vuepress/components/ScriptLoader.vue create mode 100644 docs/.vuepress/plugins/examples/add-code-for-preset.js create mode 100644 docs/.vuepress/plugins/examples/code-builder.js create mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/buildAngularBody.js create mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/buildJavascriptBody.js create mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/buildReactBody.js create mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/buildVue3Body.js create mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/buildVueBody.js create mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/getBody.js create mode 100644 docs/.vuepress/plugins/examples/examples.js create mode 100644 docs/.vuepress/plugins/examples/stackblitz.js create mode 100644 docs/examples/demo/example1.css create mode 100644 docs/examples/demo/example1.html create mode 100644 docs/examples/demo/example1.js create mode 100644 docs/examples/demo/example1.ts diff --git a/docs/.vuepress/components/ScriptLoader.vue b/docs/.vuepress/components/ScriptLoader.vue new file mode 100644 index 0000000000..c77d3eb329 --- /dev/null +++ b/docs/.vuepress/components/ScriptLoader.vue @@ -0,0 +1,39 @@ + + + diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index d966d28666..1382de8cdf 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -2,6 +2,7 @@ const highlight = require('./highlight'); const regexPlugin = require('markdown-it-regex').default; const footnotePlugin = require('markdown-it-footnote'); const searchBoxPlugin = require('./plugins/search-box'); +const examples = require('./plugins/examples/examples'); const HyperFormula = require('../../dist/hyperformula.full'); const fs = require('fs'); const path = require('path'); @@ -57,6 +58,7 @@ module.exports = { base: '/', plugins: [ searchBoxPlugin, + ['container', examples('1.0.0', 'docs')], // [ // 'vuepress-plugin-clean-urls', // { diff --git a/docs/.vuepress/plugins/examples/add-code-for-preset.js b/docs/.vuepress/plugins/examples/add-code-for-preset.js new file mode 100644 index 0000000000..c5ec28205d --- /dev/null +++ b/docs/.vuepress/plugins/examples/add-code-for-preset.js @@ -0,0 +1,53 @@ +/** + * Regular expression used to match the export default statement in the code. + * + * @type {RegExp} + */ +const EXPORT_DEFAULT_REGEX = /export default (?:function ([\w]*)|([\w]*))(?:;)/; + +const addCodeForPreset = (code, preset, id) => { + const match = code.match(EXPORT_DEFAULT_REGEX); + const exportId = match?.[1] || match?.[2] || code.includes('export class AppModule'); + + const renderImportPart = () => { + if (/vue3(-.*)?/.test(preset)) { + return 'import { createApp } from \'vue\';'; + } + + return ''; + }; + + const renderCreatePart = () => { + if (/react(-.*)?/.test(preset)) { + return `ReactDOM.render(<${exportId} />, document.getElementById("${id}"));`; + } else if (/vue3(-.*)?/.test(preset)) { + return `const app = createApp(${exportId}); +app.mount('#${id}');`; + } else if (/vue(-.*)?/.test(preset)) { + return `new Vue({ +...${exportId}, +el: '#${id}', +});`; + } else if (/angular(-.*)?/.test(preset)) { + return `import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch(err => { console.error(err) });`; + } + + return ''; + }; + + const importPart = renderImportPart(); + const renderPart = renderCreatePart(); + + if (exportId) { + return `${importPart ? `${importPart}\n` : ''}${code}${renderPart ? `\n${renderPart}` : ''}` + .replace(EXPORT_DEFAULT_REGEX, ''); + } + + return code; +}; + +module.exports = { addCodeForPreset }; diff --git a/docs/.vuepress/plugins/examples/code-builder.js b/docs/.vuepress/plugins/examples/code-builder.js new file mode 100644 index 0000000000..9c48be9ae4 --- /dev/null +++ b/docs/.vuepress/plugins/examples/code-builder.js @@ -0,0 +1,32 @@ +const { transformSync } = require('@babel/core'); + +const babelConfig = { + presets: [ + '@babel/preset-env', + '@babel/preset-react', + '@babel/preset-typescript', + ], + plugins: [ + '@babel/plugin-transform-modules-commonjs', + '@babel/plugin-syntax-class-properties', + ['@babel/plugin-proposal-decorators', { legacy: true }], + ['@babel/plugin-proposal-class-properties', { loose: true }], + ['@babel/plugin-proposal-private-methods', { loose: true }], + ['@babel/plugin-proposal-private-property-in-object', { loose: true }] + ], + targets: { + ie: 9 + } +}; + +const buildCode = (filename, contentJs, relativePath = '') => { + try { + return transformSync(contentJs, { ...babelConfig, filename }).code; + } catch (error) { + // eslint-disable-next-line + console.error(`Babel error when building ${relativePath}`); + throw error; + } +}; + +module.exports = { buildCode }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/buildAngularBody.js b/docs/.vuepress/plugins/examples/code-structure-builder/buildAngularBody.js new file mode 100644 index 0000000000..01d8b125d8 --- /dev/null +++ b/docs/.vuepress/plugins/examples/code-structure-builder/buildAngularBody.js @@ -0,0 +1,233 @@ +const buildAngularBody = ({ html, js, version, hyperformulaVersion }) => { + const codeParts = js.matchAll(/\/\* file:(.*?)\*\/(.*?)\/\* end-file \*\//gs); + const codePartsObject = [...codeParts]?.reduce((acc, curr) => { + const name = curr?.[1].trim(); + const content = curr?.[2].trim(); + // eslint-disable-next-line + const path = 'src/app/' + name; + + if (name.includes('.ts')) { + acc[path] = { + content + }; + } + + return acc; + }, {}) ?? {}; + + return { + files: { + 'package.json': { + content: `{ + "name": "handsontable", + "version": "1.0.0", + "description": "", + "scripts": { + "ng": "ng", + "start": "ng serve --disable-host-check", + "build": "ng build" + }, + "dependencies": { + "@angular/animations": "^17.3.0", + "@angular/common": "^17.3.0", + "@angular/compiler": "^17.3.0", + "@angular/core": "^17.3.0", + "@angular/forms": "^17.3.0", + "@angular/platform-browser": "^17.3.0", + "@angular/platform-browser-dynamic": "^17.3.0", + "@angular/router": "^17.3.0", + "numbro": "^2.4.0", + "rxjs": "^7.8.0", + "tslib": "^2.6.2", + "zone.js": "^0.14.4", + "hyperformula": "${hyperformulaVersion}", + "handsontable": "${version}", + "@handsontable/angular": "${version}" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^17.3.0", + "@angular/localize": "latest", + "@angular/service-worker": "latest", + "@angular/cli": "^17.3.0", + "@angular/compiler-cli": "^17.3.0", + "@types/node": "12.20.7", + "ts-node": "8.3.0", + "typescript": "5.4.2" + } +}`, + }, + 'angular.json': { + content: `{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "sandbox": { + "projectType": "application", + "schematics": { + "@schematics/angular:application": { + "strict": true + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "tsconfig.app.json", + "styles": [ + "node_modules/handsontable/dist/handsontable.full.css" + ], + "scripts": [], + "preserveSymlinks": true, + "allowedCommonJsDependencies": [ + "core-js", + "@handsontable/pikaday", + "numbro" + ] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "sandbox:build" + }, + "configurations": { + "production": { + "browserTarget": "sandbox:build:production" + }, + "development": { + "browserTarget": "sandbox:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "sandbox:build" + } + } + } + } + }, + "defaultProject": "sandbox", + "cli": { + "analytics": false + } +}`, + }, + 'tsconfig.app.json': { + content: `/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +}` + }, + 'tsconfig.json': { + content: `/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "allowSyntheticDefaultImports": true, + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "target": "ES2022", + "module": "ES2022", + "useDefineForClassFields": false, + "lib": [ + "ES2022", + "dom" + ] + }, + "angularCompilerOptions": { + "disableTypeScriptVersionCheck": true, + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +}` + }, + 'src/index.html': { + content: ` + + + + Handsontable for Angular example + + + + + ${html || ''} + +`, + }, + 'src/main.ts': { + content: `import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { AppModule } from './app/app.module'; + +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); +`, + }, + ...codePartsObject + }, + }; +}; + +module.exports = { buildAngularBody }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/buildJavascriptBody.js b/docs/.vuepress/plugins/examples/code-structure-builder/buildJavascriptBody.js new file mode 100644 index 0000000000..7063d249c0 --- /dev/null +++ b/docs/.vuepress/plugins/examples/code-structure-builder/buildJavascriptBody.js @@ -0,0 +1,92 @@ +const buildJavascriptBody = ({ id, html, js, css, version, hyperformulaVersion, sandbox, lang }) => { + if (sandbox === 'stackblitz') { + return { + files: { + 'package.json': { + content: `{ + "name": "handsontable", + "version": "1.0.0", + "description": "", + "dependencies": { + "hyperformula": "${hyperformulaVersion}", + "handsontable": "${version}" + } + }` + }, + 'index.html': { + content: ` + + + + + Handsontable + + + + ${html || `
`} + + ` + }, + 'styles.css': { + content: css + }, + [`index.${lang}`]: { + content: `import './styles.css' +${js}` + }, + } + }; + } + + return { + files: { + 'package.json': { + content: `{ + "name": "handsontable", + "version": "1.0.0", + "description": "", + "main": "index.html", + "scripts": { + "start": "parcel --no-source-maps index.html --open", + "build": "parcel build index.html" + }, + "dependencies": { + "hyperformula": "${hyperformulaVersion}", + "handsontable": "${version}" + }, + "devDependencies": { + "@babel/core": "7.2.0", + "parcel-bundler": "^1.6.1" + } +}` + }, + 'index.html': { + content: ` + + + + + Handsontable + + ${js.includes('import { HyperFormula } from \'hyperformula\';') + ? '' + : ''} + + + + ${html || `
`} + + +` + }, + 'src/styles.css': { + content: css + }, + [`src/index.${lang}`]: { + content: js.replace('import { HyperFormula } from \'hyperformula\';', '') + } + } + }; +}; + +module.exports = { buildJavascriptBody }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/buildReactBody.js b/docs/.vuepress/plugins/examples/code-structure-builder/buildReactBody.js new file mode 100644 index 0000000000..1f2ccb4e62 --- /dev/null +++ b/docs/.vuepress/plugins/examples/code-structure-builder/buildReactBody.js @@ -0,0 +1,207 @@ +const buildReactBody = ({ js, css, version, hyperformulaVersion, preset, sandbox, lang }) => { + const addReduxDependencies = preset.includes('redux') + ? ` + "redux": "^4.0.0", + "react-redux": "^7.2.4",` + : ''; + + const addAdvancedDependencies = preset.includes('advanced') + ? `"redux": "^4.0.0", + "react-redux": "^7.2.4", + "react-colorful": "5.6.1", + "react-star-rating-component": "1.4.1",` + : ''; + + const tsconfig = lang === 'tsx' ? { + 'tsconfig.json': { + content: `{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "moduleResolution": "node", + "noResolve": false, + "noImplicitAny": false, + "allowJs": true, + "jsx": "react", + "skipLibCheck": true, + "lib": [ + "dom", + "es2020" + ] + }, + "exclude": [ + "./node_modules/**/*" + ] +}` + } + } : {}; + + if (sandbox === 'stackblitz') { + return { + files: { + 'package.json': { + content: `{ + "name": "handsontable", + "version": "1.0.0", + "description": "", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0",${addReduxDependencies}${addAdvancedDependencies} + "hyperformula": "${hyperformulaVersion}", + "handsontable": "${version}", + "@handsontable/react": "${version}"${lang === 'tsx' ? `, + "@types/react": "18.0.21", + "@types/react-dom": "18.0.6", + "typescript": "5.5.2"` : '' +} + }, + ${lang === 'tsx' ? + `"devDependencies": { + "react-scripts-ts": "latest" + },` : '' +} + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +}` + }, + 'public/index.html': { + content: ` + + + + + Handsontable + + + + +
+ + +` + }, + 'src/styles.css': { + content: css + }, + [`src/index.${lang === 'jsx' ? 'js' : 'tsx'}`]: { + content: `import React, { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./styles.css"; +import ExampleComponent from "./ExampleComponent"; + +const rootElement = document.getElementById("root"); +const root = createRoot(rootElement); + +root.render( + + + +);` + }, + [`src/ExampleComponent.${lang}`]: { + content: `import React from "react"; +${js}` + }, + ...tsconfig + } + }; + } + + return { + files: { + 'package.json': { + content: `{ + "name": "handsontable", + "version": "1.0.0", + "description": "", + "main": "src/index.${lang}", + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0",${addReduxDependencies}${addAdvancedDependencies} + "handsontable": "${version}", + "@handsontable/react": "${version}"${lang === 'tsx' ? `, + "@types/react": "18.0.21", + "@types/react-dom": "18.0.6", + "typescript": "5.5.2"` : '' +} + }, + "devDependencies": { + "react-scripts": "^5.0.1" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +}` + }, + 'public/index.html': { + content: ` + + + + + Handsontable + ${js.includes('import { HyperFormula } from \'hyperformula\';') + ? '' + : ''} + + + + +
+ + +` + }, + 'src/styles.css': { + content: css + }, + [`src/index.${lang}`]: { + content: `import * as React from "react"; +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./styles.css"; +import ExampleComponent from "./ExampleComponent"; + +const rootElement = document.getElementById("root"); +const root = createRoot(rootElement); + +root.render( + + + +);` + }, + [`src/ExampleComponent.${lang}`]: { + content: `import * as React from "react"; +${js.replace('import { HyperFormula } from \'hyperformula\';', '')}` + }, + ...tsconfig + } + }; + +}; + +module.exports = { buildReactBody }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/buildVue3Body.js b/docs/.vuepress/plugins/examples/code-structure-builder/buildVue3Body.js new file mode 100644 index 0000000000..64812a86e5 --- /dev/null +++ b/docs/.vuepress/plugins/examples/code-structure-builder/buildVue3Body.js @@ -0,0 +1,67 @@ +const buildVue3Body = ({ id, html, js, css, version, hyperformulaVersion, preset }) => { + const addVuexDependencies = preset.includes('vuex') + ? ` + "vuex": "^4.0.2",` + : ''; + + return { + files: { + 'package.json': { + content: `{ + "name": "handsontable", + "version": "1.0.0", + "description": "", + "main": "src/main.js", + "scripts": { + "start": "vue-cli-service serve", + "build": "vue-cli-service build" + }, + "dependencies": { + "vue": "3.2.45",${addVuexDependencies} + "hyperformula": "${hyperformulaVersion}", + "handsontable": "${version}", + "@handsontable/vue3": "${version}" + }, + "devDependencies": { + "@vue/cli-service": "5.0.8" + } +}` + }, + 'vue.config.js': { + content: `module.exports = { + runtimeCompiler: true +}` + }, + 'public/index.html': { + content: ` + + + + + Handsontable + + + + ${html || `
`} + +` + }, + 'src/styles.css': { + content: css + }, + 'src/main.js': { + content: `import { createApp } from "vue"; +import "./styles.css"; +import ExampleComponent from "./ExampleComponent.js"; + +createApp(ExampleComponent).mount("#${id}"); +` + }, + 'src/ExampleComponent.js': { + content: js + } + } + }; +}; + +module.exports = { buildVue3Body }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/buildVueBody.js b/docs/.vuepress/plugins/examples/code-structure-builder/buildVueBody.js new file mode 100644 index 0000000000..3d20cdf68c --- /dev/null +++ b/docs/.vuepress/plugins/examples/code-structure-builder/buildVueBody.js @@ -0,0 +1,76 @@ +const buildVueBody = ({ id, html, js, css, version, hyperformulaVersion, preset }) => { + const addVuexDependencies = preset.includes('vuex') + ? ` + "vuex": "^3.6.2",` + : ''; + const addAdvancedDependencies = preset.includes('advanced') + ? ` + "vuex": "^3.6.2", + "vue-color": "2.8.1", + "vue-star-rating": "1.7.0",` + : ''; + + return { + files: { + 'package.json': { + content: `{ + "name": "handsontable", + "version": "1.0.0", + "description": "", + "main": "src/main.js", + "scripts": { + "start": "vue-cli-service serve", + "build": "vue-cli-service build" + }, + "dependencies": { + "vue": "2.7.14",${addVuexDependencies}${addAdvancedDependencies} + "hyperformula": "${hyperformulaVersion}", + "handsontable": "${version}", + "@handsontable/vue": "${version}" + }, + "devDependencies": { + "@vue/cli-service": "5.0.8" + } +}` + }, + 'vue.config.js': { + content: `module.exports = { + runtimeCompiler: true +}` + }, + 'public/index.html': { + content: ` + + + + + Handsontable + + + + ${html || `
`} + +` + }, + 'src/styles.css': { + content: css + }, + 'src/main.js': { + content: `import Vue from "vue"; +import "./styles.css"; +import ExampleComponent from "./ExampleComponent.js"; + +new Vue({ + ...ExampleComponent, + el: '#${id}', +}); +` + }, + 'src/ExampleComponent.js': { + content: js + }, + } + }; +}; + +module.exports = { buildVueBody }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/getBody.js b/docs/.vuepress/plugins/examples/code-structure-builder/getBody.js new file mode 100644 index 0000000000..d125067911 --- /dev/null +++ b/docs/.vuepress/plugins/examples/code-structure-builder/getBody.js @@ -0,0 +1,42 @@ +const { buildAngularBody } = require('./buildAngularBody'); +const { buildJavascriptBody } = require('./buildJavascriptBody'); +const { buildReactBody } = require('./buildReactBody'); +const { buildVue3Body } = require('./buildVue3Body'); +const { buildVueBody } = require('./buildVueBody'); + +const getBody = ({ id, html, js, css, version, preset, sandbox, lang }) => { + const hyperformulaVersion = '^2.4.0'; + + if (/hot(-.*)?/.test(preset)) { + return buildJavascriptBody({ + id, + html, + js, + css, + version, + hyperformulaVersion, + sandbox, + lang: lang === 'JavaScript' ? 'js' : 'ts' + }); + } else if (/react(-.*)?/.test(preset)) { + return buildReactBody({ + js, + css, + version, + hyperformulaVersion, + preset, + sandbox, + lang: lang === 'JavaScript' ? 'jsx' : 'tsx' + }); + } else if (/vue3(-.*)?/.test(preset)) { + return buildVue3Body({ id, html, js, css, version, hyperformulaVersion, preset }); + } else if (/vue(-.*)?/.test(preset)) { + return buildVueBody({ id, html, js, css, version, hyperformulaVersion, preset }); + } else if (/angular(-.*)?/.test(preset)) { + return buildAngularBody({ html, js, version, hyperformulaVersion }); + } + + return undefined; +}; + +module.exports = { getBody }; diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js new file mode 100644 index 0000000000..6ce70b0de2 --- /dev/null +++ b/docs/.vuepress/plugins/examples/examples.js @@ -0,0 +1,247 @@ +/** + * Matches into: `example #ID .class :preset --css 2 --html 0 --js 1 --ts 3 --no-edit`. + * + * @type {RegExp} + */ +const EXAMPLE_REGEX = /^(example)\s*(#\S*|)\s*(\.\S*|)\s*(:\S*|)\s*([\S|\s]*)$/; +const Token = require('markdown-it/lib/token'); +const { buildCode } = require('./code-builder'); +const { addCodeForPreset } = require('./add-code-for-preset'); +const { stackblitz } = require('./stackblitz'); + +const tab = (tabName, token, id) => { + if (!token) return []; + + const openTSDivToken = new Token('html_block', '', 1); + const closeDivToken = new Token('html_block', '', -1); + + openTSDivToken.content = ``; + closeDivToken.content = ''; + + return [ + openTSDivToken, + // token, + closeDivToken + ]; +}; + +const parsePreview = (content) => { + if (!content) return ''; + + return content + // Remove the all "/* start:skip-in-compilation */" and "/* end:skip-in-compilation */" comments + .replace(/\/\*(\s+)?(start|end):skip-in-compilation(\s+)?\*\/\n/gm, '') + // Remove the code between "/* start:skip-in-preview */" and "/* end:skip-in-preview */" expressions + .replace(/\/\*(\s+)?start:skip-in-preview(\s+)?\*\/\n.*?\/\*(\s+)?end:skip-in-preview(\s+)?\*\/\n/msg, '') + // Remove /* end-file */ + .replace(/\/\* end-file \*\//gm, '') + .trim(); +}; + +const parseCode = (content) => { + if (!content) return ''; + + return content + // Remove the all "/* start:skip-in-preview */" and "/* end:skip-in-preview */" comments + .replace(/\/\*(\s+)?(start|end):skip-in-preview(\s+)?\*\/\n/gm, '') + // Remove the code between "/* start:skip-in-compilation */" and "/* end:skip-in-compilation */" expressions + // eslint-disable-next-line max-len + .replace(/\/\*(\s+)?start:skip-in-compilation(\s+)?\*\/\n.*?\/\*(\s+)?end:skip-in-compilation(\s+)?\*\/\n/msg, '') + // Remove /* end-file */ + .replace(/\/\* end-file \*\//gm, ''); +}; + +const parseCodeSandbox = (content) => { + if (!content) return ''; + + return content + // Remove the all "/* start:skip-in-preview */" and "/* end:skip-in-preview */" comments + .replace(/\/\*(\s+)?(start|end):skip-in-preview(\s+)?\*\/\n/gm, '') + // Remove the all "/* start:skip-in-compilation */" and "/* end:skip-in-compilation */" comments + .replace(/\/\*(\s+)?(start|end):skip-in-compilation(\s+)?\*\/\n/gm, ''); +}; + +const getCodeToken = (jsToken, tsToken) => { + const code = new Token('inline', '', 1); + const openJSDivToken = new Token('container_div_open', 'div', 1); + const openTSDivToken = new Token('container_div_open', 'div', 1); + const closeDivToken = new Token('container_div_close', 'div', -1); + + openJSDivToken.attrSet('class', 'tab-content-js'); + openJSDivToken.attrSet('v-if', '$parent.$parent.selectedLang === \'JavaScript\''); + openTSDivToken.attrSet('class', 'tab-content-ts'); + openTSDivToken.attrSet('v-if', '$parent.$parent.selectedLang === \'TypeScript\''); + + code.children = [ + openJSDivToken, + jsToken, + closeDivToken + ]; + + if (tsToken) { + code.children.push(openTSDivToken); + code.children.push(tsToken); + code.children.push(closeDivToken); + } + + return code; +}; + +module.exports = function(docsVersion, base) { + return { + type: 'example', + render(tokens, index, _opts, env) { + const token = tokens[index]; + const m = token.info.trim().match(EXAMPLE_REGEX); + + if (token.nesting === 1 && m) { + // open preview + let [, , id, klass, preset, args] = m; + + id = id ? id.substring(1) : 'example1'; + klass = klass ? klass.substring(1) : ''; + preset = preset ? preset.substring(1) : 'hot'; + args = args || ''; + + const htmlPos = args.match(/--html (\d*)/)?.[1]; + const htmlIndex = htmlPos ? index + Number.parseInt(htmlPos, 10) : 0; + const htmlToken = htmlPos ? tokens[htmlIndex] : undefined; + const htmlContent = htmlToken + ? htmlToken.content + : `
`; + const htmlContentRoot = `
${htmlContent}
`; + + const cssPos = args.match(/--css (\d*)/)?.[1]; + const cssIndex = cssPos ? index + Number.parseInt(cssPos, 10) : 0; + const cssToken = cssPos ? tokens[cssIndex] : undefined; + const cssContent = cssToken ? cssToken.content : ''; + + const jsPos = args.match(/--js (\d*)/)?.[1] || 1; + const jsIndex = jsPos ? index + Number.parseInt(jsPos, 10) : 0; + const jsToken = jsPos ? tokens[jsIndex] : undefined; + + const tsPos = args.match(/--ts (\d*)/)?.[1]; + const tsIndex = tsPos ? index + Number.parseInt(tsPos, 10) : 0; + const tsToken = tsPos ? tokens[tsIndex] : undefined; + + // Parse code + // const jsTokenWithBasePath = jsToken?.content?.replaceAll('{{$basePath}}', base); + // const tsTokenWithBasePath = tsToken?.content?.replaceAll('{{$basePath}}', base); + // const codeToCompile = parseCode(jsTokenWithBasePath); + // const tsCodeToCompile = parseCode(tsTokenWithBasePath); + // const codeToCompileSandbox = parseCodeSandbox(jsTokenWithBasePath); + // const tsCodeToCompileSandbox = parseCodeSandbox(tsTokenWithBasePath); + // const codeToPreview = parsePreview(jsTokenWithBasePath); + // const tsCodeToPreview = parsePreview(tsTokenWithBasePath); + + // Replace token content + // if (jsToken) jsToken.content = codeToPreview; + + // if (tsToken) tsToken.content = tsCodeToPreview; + + [htmlIndex, jsIndex, tsIndex, cssIndex].filter(x => !!x).sort().reverse().forEach((x) => { + tokens.splice(x, 1); + }); + + const newTokens = [ + new Token('container_div_open', 'div', 1), + new Token('container_div_close', 'div', -1), + new Token('container_div_open', 'div', 1), + new Token('container_div_close', 'div', -1), + ]; + + tokens.splice(index + 1, 0, ...newTokens); + + // const codeForPreset = addCodeForPreset(codeToCompile, preset, id); + // const tsCodeForPreset = addCodeForPreset(tsCodeToCompile, preset, id); + // const code = buildCode( + // id + (preset.includes('angular') ? '.ts' : '.jsx'), + // codeForPreset, + // env.relativePath + // ); + // const encodedCode = encodeURI( + // `useHandsontable('${docsVersion}', function(){${code}}, '${preset}')` + // ); + const activeTab = `${args.match(/--tab (code|html|css|preview)/)?.[1] ?? 'preview'}-tab-${id}`; + const noEdit = !!args.match(/--no-edit/)?.[0]; + // const isRTL = /layoutDirection(.*)'rtl'/.test(codeToCompile) || /dir="rtl"/.test(htmlContent); + const isActive = `$parent.$parent.isScriptLoaderActivated('${id}')`; + const selectedLang = '$parent.$parent.selectedLang'; + const isJavaScript = preset.includes('hot'); + const isReact = preset.includes('react'); + const isReactOrJavaScript = isJavaScript || isReact; + + return ''; + return ` +
+ +
+
+
+ + + +
+
+ ${!true + ? stackblitz( + id, + htmlContent, + codeToCompileSandbox, + cssContent, + docsVersion, + preset, + 'JavaScript' + ) + : ''} +
+
+ ${!true + ? stackblitz( + id, + htmlContent, + tsCodeToCompileSandbox, + cssContent, + docsVersion, + preset, + 'TypeScript' + ) + : ''} +
+ + + +
+
+
+ + `; + } else { + // close preview + return ''; + return '
'; + } + }, + }; +}; diff --git a/docs/.vuepress/plugins/examples/stackblitz.js b/docs/.vuepress/plugins/examples/stackblitz.js new file mode 100644 index 0000000000..c8432b738d --- /dev/null +++ b/docs/.vuepress/plugins/examples/stackblitz.js @@ -0,0 +1,53 @@ +const { getBody } = require('./code-structure-builder/getBody'); + +const stackblitz = (id, html, js, css, docsVersion, preset, lang) => { + const body = getBody({ id, html, js, css, docsVersion, preset, sandbox: 'stackblitz', lang }); + + const projects = body?.files + ? Object.entries(body?.files).map(([key, value]) => ( + `` + )) : []; + + const addReactDependencies = preset.includes('react') + // eslint-disable-next-line max-len + ? ', "@handsontable/react": "latest", "react": "latest", "react-dom": "latest", "redux": "latest", "react-redux": "latest", "react-colorful": "latest", "react-star-rating-component": "latest", "@types/react": "latest", "@types/react-dom": "latest"' + : ''; + + const getTemplate = () => { + if (preset.includes('react')) return 'create-react-app'; + + if (preset.includes('hot') && lang === 'JavaScript') return 'javascript'; + + if (preset.includes('hot') && lang === 'TypeScript') return 'typescript'; + + return 'node'; + }; + + return ` +
+ ${projects.join('\n')} + + + + + + +
+ `; +}; + +module.exports = { stackblitz }; diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css new file mode 100644 index 0000000000..ec2e4fd974 --- /dev/null +++ b/docs/examples/demo/example1.css @@ -0,0 +1,5 @@ +h3.demo-preview { + margin-bottom: 0.3rem !important; + padding-top: 0 !important; + margin-top: 0.5rem !important; +} \ No newline at end of file diff --git a/docs/examples/demo/example1.html b/docs/examples/demo/example1.html new file mode 100644 index 0000000000..178511d36e --- /dev/null +++ b/docs/examples/demo/example1.html @@ -0,0 +1,2 @@ +

Hello

+
diff --git a/docs/examples/demo/example1.js b/docs/examples/demo/example1.js new file mode 100644 index 0000000000..3231c55b72 --- /dev/null +++ b/docs/examples/demo/example1.js @@ -0,0 +1,4 @@ +// import { HyperFormula } from 'hyperformula'; + +const container = document.querySelector('#container'); + container.innerHTML = 'world!'; diff --git a/docs/examples/demo/example1.ts b/docs/examples/demo/example1.ts new file mode 100644 index 0000000000..4cfc7aae91 --- /dev/null +++ b/docs/examples/demo/example1.ts @@ -0,0 +1,4 @@ +// import { HyperFormula } from 'hyperformula'; + +const container = document.querySelector('#container')! +container.innerHTML = 'world!' diff --git a/docs/guide/demo.md b/docs/guide/demo.md index 25c092022f..e1a9785396 100644 --- a/docs/guide/demo.md +++ b/docs/guide/demo.md @@ -1,16 +1,15 @@ # Demo - +::: example #example1 --html 1 --css 2 --js 3 --ts 4 -In this demo, you can see how HyperFormula handles basic operations by using API methods, such as: +@[code](@/examples/demo/example1.html) -* `buildEmpty` static method to initialize the instance -* `addSheet` method to add a new sheet -* `setCellContents` method to add content -* `getSheetId` method to retrieve the sheet's ID -* `getCellValue` method to get the value of a cell -* `calculateFormula` method to calculate a formula -* `getCellFormula` method to retrieve a formula from a cell +@[code](@/examples/demo/example1.css) + +@[code](@/examples/demo/example1.js) + +@[code](@/examples/demo/example1.ts) + +::: + +paragraph diff --git a/package-lock.json b/package-lock.json index 794de7c52b..dcbe9d3b50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,17 @@ "devDependencies": { "@babel/cli": "^7.8.4", "@babel/core": "^7.8.4", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-decorators": "^7.13.5", + "@babel/plugin-proposal-private-methods": "^7.13.0", + "@babel/plugin-proposal-private-property-in-object": "^7.13.0", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", "@babel/plugin-transform-runtime": "^7.8.3", + "@babel/plugin-transform-typescript": "^7.24.7", "@babel/preset-env": "^7.8.4", + "@babel/preset-react": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", "@babel/register": "^7.9.0", "@babel/runtime": "^7.18.9", "@microsoft/tsdoc": "^0.12.16", @@ -168,12 +177,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", - "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", "dev": true, "dependencies": { - "@babel/types": "^7.24.9", + "@babel/types": "^7.25.6", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -224,19 +233,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", - "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", + "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", "@babel/helper-member-expression-to-functions": "^7.24.8", "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/traverse": "^7.25.4", "semver": "^6.3.1" }, "engines": { @@ -400,14 +407,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", - "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7" + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -525,10 +532,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", "dev": true, + "dependencies": { + "@babel/types": "^7.25.6" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -634,11 +644,35 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, "engines": { "node": ">=6.9.0" }, @@ -907,6 +941,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", @@ -1524,6 +1573,71 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", + "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dev": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-regenerator": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", @@ -1651,6 +1765,25 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", + "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", @@ -1809,6 +1942,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", @@ -1823,6 +1968,45 @@ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/register": { "version": "7.24.6", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", @@ -1861,33 +2045,30 @@ } }, "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dev": true, "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", - "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.8", - "@babel/types": "^7.24.8", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1896,9 +2077,9 @@ } }, "node_modules/@babel/types": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", - "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.24.8", diff --git a/package.json b/package.json index 579e6f844f..ee79739bbf 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,15 @@ "@babel/preset-env": "^7.8.4", "@babel/register": "^7.9.0", "@babel/runtime": "^7.18.9", + "@babel/preset-react": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-proposal-decorators": "^7.13.5", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-private-methods": "^7.13.0", + "@babel/plugin-proposal-private-property-in-object": "^7.13.0", + "@babel/plugin-transform-typescript": "^7.24.7", "@microsoft/tsdoc": "^0.12.16", "@types/jasmine": "^4.0.0", "@types/jest": "^26.0.0", From 87964f2edf3806d270b6bbdbe332d586ea428847 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Wed, 11 Sep 2024 15:51:02 +0200 Subject: [PATCH 02/41] Add markdown-it plugins --- docs/.vuepress/config.js | 8 ++ docs/.vuepress/plugins/examples/examples.js | 2 +- .../index.js | 115 ++++++++++++++++++ .../onlyForContainerHelpers.js | 88 ++++++++++++++ .../markdown-it-header-anchor/index.js | 39 ++++++ .../markdown-it-header-injection/index.js | 43 +++++++ .../markdown-it-include-code-snippet/index.js | 105 ++++++++++++++++ docs/guide/demo.md | 18 ++- 8 files changed, 412 insertions(+), 6 deletions(-) create mode 100644 docs/.vuepress/plugins/markdown-it-conditional-container/index.js create mode 100644 docs/.vuepress/plugins/markdown-it-conditional-container/onlyForContainerHelpers.js create mode 100644 docs/.vuepress/plugins/markdown-it-header-anchor/index.js create mode 100644 docs/.vuepress/plugins/markdown-it-header-injection/index.js create mode 100644 docs/.vuepress/plugins/markdown-it-include-code-snippet/index.js diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 1382de8cdf..1c2973bf99 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -4,6 +4,10 @@ const footnotePlugin = require('markdown-it-footnote'); const searchBoxPlugin = require('./plugins/search-box'); const examples = require('./plugins/examples/examples'); const HyperFormula = require('../../dist/hyperformula.full'); +const firstHeaderInjection = require('./plugins/markdown-it-header-injection'); +const headerAnchor = require('./plugins/markdown-it-header-anchor'); +const conditionalContainer = require('./plugins/markdown-it-conditional-container'); +const includeCodeSnippet = require('./plugins/markdown-it-include-code-snippet'); const fs = require('fs'); const path = require('path'); @@ -111,6 +115,10 @@ module.exports = { replace: () => `'${HyperFormula.releaseDate}'` }) md.use(footnotePlugin) + md.use(includeCodeSnippet) + md.use(conditionalContainer) + md.use(firstHeaderInjection) + md.use(headerAnchor) } }, // TODO: It doesn't work. It's seems that this option is bugged. Documentation says that this option is configurable, diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js index 6ce70b0de2..d17b7e4dde 100644 --- a/docs/.vuepress/plugins/examples/examples.js +++ b/docs/.vuepress/plugins/examples/examples.js @@ -20,7 +20,7 @@ const tab = (tabName, token, id) => { return [ openTSDivToken, - // token, + token, closeDivToken ]; }; diff --git a/docs/.vuepress/plugins/markdown-it-conditional-container/index.js b/docs/.vuepress/plugins/markdown-it-conditional-container/index.js new file mode 100644 index 0000000000..23e07b2204 --- /dev/null +++ b/docs/.vuepress/plugins/markdown-it-conditional-container/index.js @@ -0,0 +1,115 @@ +const chalk = require('chalk'); + +/* eslint-disable */ +/** + * Container used to display blocks of content only for to specific frameworks. + * + * Usage: + * ``` + * ::: only-for react + * Content to be displayed only for React documentation. + * ::: + * + * ::: only-for javascript react vue + * Content to be displayed only for JS, React and Vue documentation. + * ::: + * ``` + */ +module.exports = function conditionalContainer(markdown) { + const openAndCloseTagOneliner = /::: only-for (((react|javascript) ?)+)(.*?):::$/ms; // It is multi line text. + const openTokenContent = /(?:\n?)::: only-for (((react|javascript) ?)+)\n?/; + const fullMatchOpenToken = /^(?:\n?)::: only-for (((react|javascript) ?)+)\n?$/; + const closeTokenContent = /(?:\n?):::(?:\n?)$/; + const fullMatchCloseToken = /^(?:\n?):::(?:\n?)$/; + const markupForCustomContainer = ':::'; + const newLineTokenType = 'softbreak'; + const capturedGroupIndex = 1; + let endIndex; + + const removeValueAndNewLine = ({ token, regexp, env }) => { + // Removing value from token's content. + token.content = token.content.replace(regexp, ''); + + // Some tokens may not have children. Children are component parts of the displayed text in most cases. + if (token.children === null) { + return; + } + + let childrenIndex = token.children.findIndex(childrenToken => regexp.test(childrenToken.content)); + + // Some tokens contains children which also represents the removed value (and they are displayed in the output file). + if (childrenIndex !== -1) { + const nextElement = token.children[childrenIndex + 1]; + const previousElement = token.children[childrenIndex - 1]; + let howMany = 1; + + if (childrenIndex > 0 && previousElement.type === newLineTokenType) { + childrenIndex -= 1; + howMany += 1; + } + + if (nextElement?.type === newLineTokenType) { + howMany += 1; + } + + token.children.splice(childrenIndex, howMany); + } else { + // eslint-disable-next-line no-console + console.error(`${chalk.red('\nUnexpected error while processing a conditional container (::: only-for) in the file ' + `"${env.relativePath}".` + + ` Please check the file or the resulting page "${env.frontmatter.permalink}".` + )}`); + } + }; + + const cleanTokens = ({ tokens, token, tokenIndex, preciseRegexp, lessPreciseRegexp, env }) => { + if (preciseRegexp.test(token.content)) { + tokens.splice(tokenIndex, 1); + + } else { + removeValueAndNewLine({ token, regexp: lessPreciseRegexp, env }); + } + }; + + const findAndRemove = (state) => { + const relativePath = state.env?.relativePath; // Sometimes the `env` key is an empty object. + + if (relativePath === void 0) { + return; + } + + const env = state.env; + + for (let index = state.tokens.length - 1; index >= 0; index -= 1) { + const token = state.tokens[index]; + // We don't create custom container intentionally. It can create paragraphs or break listed elements. + const isNotNativeContainer = token.markup !== markupForCustomContainer; + + if (isNotNativeContainer) { + if (openAndCloseTagOneliner.test(token.content)) { + const onlyForFrameworks = openAndCloseTagOneliner.exec(token.content)[capturedGroupIndex].split(' '); + + removeValueAndNewLine({ token, regexp: openTokenContent, env }); + removeValueAndNewLine({ token, regexp: closeTokenContent, env }); + } else if (closeTokenContent.test(token.content)) { + + endIndex = index; + } else if (openTokenContent.test(token.content)) { + const onlyForFrameworks = openTokenContent.exec(token.content)[capturedGroupIndex].split(' '); + + if (endIndex === void 0) { + console.error(`${chalk.red('\nUnexpected error while processing a conditional container (::: only-for)' + + ` in the file "${getNormalizedPath(env.relativePath)}". It seems that the opening token (::: only-for)` + + ' exists, but the ending token (:::) does not.' + )}`); + } + + cleanTokens({ tokens: state.tokens, token: state.tokens[endIndex], tokenIndex: endIndex, lessPreciseRegexp: closeTokenContent, preciseRegexp: fullMatchCloseToken, env }); + cleanTokens({ tokens: state.tokens, token, tokenIndex: index, lessPreciseRegexp: openTokenContent, preciseRegexp: fullMatchOpenToken, env }); + } + } + } + }; + + markdown.core.ruler.push('conditional_container', findAndRemove); +}; diff --git a/docs/.vuepress/plugins/markdown-it-conditional-container/onlyForContainerHelpers.js b/docs/.vuepress/plugins/markdown-it-conditional-container/onlyForContainerHelpers.js new file mode 100644 index 0000000000..a715eb7710 --- /dev/null +++ b/docs/.vuepress/plugins/markdown-it-conditional-container/onlyForContainerHelpers.js @@ -0,0 +1,88 @@ +/** + * A factory for creating function for `markdown-it-anchor` plugin's `permalinkSymbol` configuration option. + * + * @param {Set} uniqueSlugs An unique set, where are stored slugs. + * @returns {Function} + */ +function getPermalinkHrefMethod(uniqueSlugs) { + return function(slug, state) { + const slugify = state.md.slugify; + const openTokenContent = /(?:\n?)::: only-for (((react|javascript) ?)+)\n?/; + const closeTokenContent = /(?:\n?):::(?:\n?)$/; + const markupForCustomContainer = ':::'; + const headerOpenType = 'heading_open'; + const headerCloseType = 'heading_close'; + let endIndex; + + if (/(.*)-(\d)+$/.test(slug) === false) { + return `#${slug}`; + } + + const handleTokensInsideOnlyForContainer = (action) => { + for (let index = state.tokens.length - 1; index >= 0; index -= 1) { + const token = state.tokens[index]; + // We don't create custom container intentionally inside `markdown-it-conditional-container` plugin. + const isNotNativeContainer = token.markup !== markupForCustomContainer; + + if (isNotNativeContainer) { + if (closeTokenContent.test(token.content)) { + + endIndex = index; + } else if (openTokenContent.test(token.content)) { + action(state.tokens.slice(index, endIndex)); + } + } + } + }; + + const getTokensInsideHeaders = (tokens) => { + return tokens.filter((_, tokenIndex) => { + if (tokenIndex === 0 || tokenIndex === tokens.length - 1) { + return false; + + } else if (tokens[tokenIndex - 1]?.type === headerOpenType && + tokens[tokenIndex + 1]?.type === headerCloseType) { + // Tokens being children of some header. + return true; + } + + return false; + }); + }; + + const getParsedSlugsFromHeaders = (tokens) => { + return getTokensInsideHeaders(tokens).map(headerContentTag => slugify(headerContentTag.content)); + }; + + const parseAndChangeDuplicatedSlug = (tokensInside) => { + getParsedSlugsFromHeaders(tokensInside).some((headerSlug) => { // Array.some for purpose of stopping the loop. + const headerSlugWithNumber = new RegExp(`${headerSlug}-(\\d)+$`); + + if (headerSlugWithNumber.test(slug)) { + // Remove the `-[number]` suffix from the permalink href attribute. + const duplicatedSlugsMatch = headerSlugWithNumber.exec(slug); + + if (duplicatedSlugsMatch) { + // Updating a set of slugs, which will be used by another method. + uniqueSlugs.add(headerSlug); + + // Removed the `-[number]` suffix. + slug = `${headerSlug}`; + + return true; // Breaks the loop. + } + } + + return false; // Continue looping. + }); + }; + + handleTokensInsideOnlyForContainer(parseAndChangeDuplicatedSlug); + + return `#${slug}`; + }; +} + +module.exports = { + getPermalinkHrefMethod, +}; diff --git a/docs/.vuepress/plugins/markdown-it-header-anchor/index.js b/docs/.vuepress/plugins/markdown-it-header-anchor/index.js new file mode 100644 index 0000000000..00188bdbdd --- /dev/null +++ b/docs/.vuepress/plugins/markdown-it-header-anchor/index.js @@ -0,0 +1,39 @@ +module.exports = function headerAnchor(markdown) { + const insertedTokenTag = 'a'; + const insertedOpenTokenType = 'link_open'; + const insertedCloseTokenType = 'link_close'; + const foundTokenTags = ['h1', 'h2', 'h3']; + const foundOpenTokenType = 'heading_open'; + + const findAndReplace = (state) => { + const Token = state.Token; + const relativePath = state.env?.relativePath; // Sometimes the `env` key is an empty object. + + if (relativePath === void 0) { + return; + } + + state.tokens.forEach((token, index) => { + // Check if token is inside `h` tag + if ( + token.type === 'inline' + && state.tokens[index - 1].type === foundOpenTokenType + && foundTokenTags.includes(state.tokens[index - 1].tag) + ) { + // Create `a` tag with href attribute + const aTagOpen = new Token(insertedOpenTokenType, insertedTokenTag, 1); + const aTagClose = new Token(insertedCloseTokenType, insertedTokenTag, -1); + const id = state.tokens[index - 1].attrGet('id'); + + aTagOpen.attrSet('href', `#${id}`); + aTagOpen.attrSet('class', 'header-link'); + + // Wrap `h` tag content with `a` tag + token.children.unshift(aTagOpen); + token.children.push(aTagClose); + } + }); + }; + + markdown.core.ruler.push('header_anchor', findAndReplace); +}; diff --git a/docs/.vuepress/plugins/markdown-it-header-injection/index.js b/docs/.vuepress/plugins/markdown-it-header-injection/index.js new file mode 100644 index 0000000000..887e97ada2 --- /dev/null +++ b/docs/.vuepress/plugins/markdown-it-header-injection/index.js @@ -0,0 +1,43 @@ +module.exports = function firstHeaderInjection(markdown) { + const insertedTokenTag = 'span'; + const insertedOpenTokenType = 'paragraph_open'; + const insertedCloseTokenType = 'paragraph_close'; + const foundTokenTag = 'h1'; + const foundOpenTokenType = 'heading_open'; + + const findAndInject = (state) => { + const Token = state.Token; + const relativePath = state.env?.relativePath; // Sometimes the `env` key is an empty object. + + if (relativePath === void 0) { + return; + } + + let insertSpan = false; + + // Find the first header and insert some element to it. + state.tokens.every((token) => { + // Next token represents a place where new HTML tag can be injected. + if (insertSpan && token.type === 'inline') { + const spanOpen = new Token(insertedOpenTokenType, insertedTokenTag, 1); + const spanClose = new Token(insertedCloseTokenType, insertedTokenTag, -1); + const text = new Token('html_block', '', 0); + + text.content = `Data Grid`; + + spanOpen.attrSet('class', 'header-framework'); + token.children.unshift(spanOpen, text, spanClose); // Add HTML element right after first `h1` tag on the site. + + return false; // Stops the iteration. + } + + if (token.type === foundOpenTokenType && token.tag === foundTokenTag) { + insertSpan = true; + } + + return true; + }); + }; + + markdown.core.ruler.push('first_header_injection', findAndInject); +}; diff --git a/docs/.vuepress/plugins/markdown-it-include-code-snippet/index.js b/docs/.vuepress/plugins/markdown-it-include-code-snippet/index.js new file mode 100644 index 0000000000..c35bd4c956 --- /dev/null +++ b/docs/.vuepress/plugins/markdown-it-include-code-snippet/index.js @@ -0,0 +1,105 @@ +const fs = require('fs'); + +const fileExists = filePath => fs.existsSync(filePath); + +const readFileContent = filePath => + (fileExists(filePath) + ? fs.readFileSync(filePath).toString() + : `Not Found: ${filePath}`); + +const parseOptions = (optionsString) => { + const parsedOptions = {}; + + optionsString + .trim() + .split(' ') + .forEach((pair) => { + const [option, value] = pair.split('='); + + parsedOptions[option] = value; + }); + + return parsedOptions; +}; + +module.exports = function includeCodeSnippet(markdown, options) { + const rootDirectory = options && options.root ? options.root : process.cwd(); + + const createDataObject = (state, position, maximum) => { + const start = position + 6; + const end = state.skipSpacesBack(maximum, position) - 1; + const [optionsString, fullpathWithAtSym] = state.src + .slice(start, end) + .trim() + .split(']('); + + const fullpath = fullpathWithAtSym.replace(/^@/, rootDirectory).trim(); + const pathParts = fullpath.split('/'); + const fileParts = pathParts[pathParts.length - 1].split('.'); + + return { + file: { + resolve: fullpath, + path: pathParts.slice(0, pathParts.length - 1).join('/'), + name: fileParts.slice(0, fileParts.length - 1).join('.'), + ext: fileParts[fileParts.length - 1], + }, + options: parseOptions(optionsString), + content: readFileContent(fullpath), + fileExists: fileExists(fullpath), + }; + }; + + // eslint-disable-next-line no-shadow + const mapOptions = ({ options }) => ({ + hasHighlight: options.highlight || false, + get meta() { + return this.hasHighlight ? options.highlight : ''; + }, + }); + + /** + * Custom parser function for handling code snippets in markdown. + * + * @param {object} state - The current state object of the markdown-it parser. + * @param {number} startLine - The line number where the code snippet starts. + * @param {number} endLine - The line number where the code snippet ends. + * @param {boolean} silent - Flag indicating whether the parser should run in silent mode. + * @returns {boolean} - Returns true if the code snippet was successfully parsed, false otherwise. + */ + function customParser(state, startLine, endLine, silent) { + const fenceMarker = '@[code]'; + const position = state.bMarks[startLine] + state.tShift[startLine]; + const maximum = state.eMarks[startLine]; + + // Early return for indented blocks + if (state.sCount[startLine] - state.blkIndent >= 4) return false; + + if (!state.src.startsWith(fenceMarker, position)) { + // Early return if fence marker is not present + return false; + } + + if (silent) { + // Handle silent mode + return true; + } + + const dataObject = createDataObject(state, position, maximum); + const optionsMapping = mapOptions(dataObject); + + const token = state.push('fence', 'code', 0); + + token.info = + (dataObject.options.lang || dataObject.file.ext) + optionsMapping.meta; + token.content = dataObject.content; + token.markup = '```'; + token.map = [startLine, startLine + 1]; + + state.line = startLine + 1; + + return true; + } + + markdown.block.ruler.before('fence', 'snippet', customParser); +}; diff --git a/docs/guide/demo.md b/docs/guide/demo.md index e1a9785396..1d4e754a42 100644 --- a/docs/guide/demo.md +++ b/docs/guide/demo.md @@ -2,14 +2,22 @@ ::: example #example1 --html 1 --css 2 --js 3 --ts 4 -@[code](@/examples/demo/example1.html) +@[code](@/docs/examples/demo/example1.html) -@[code](@/examples/demo/example1.css) +@[code](@/docs/examples/demo/example1.css) -@[code](@/examples/demo/example1.js) +@[code](@/docs/examples/demo/example1.js) -@[code](@/examples/demo/example1.ts) +@[code](@/docs/examples/demo/example1.ts) ::: -paragraph +In this demo, you can see how HyperFormula handles basic operations by using API methods, such as: + +* `buildEmpty` static method to initialize the instance +* `addSheet` method to add a new sheet +* `setCellContents` method to add content +* `getSheetId` method to retrieve the sheet's ID +* `getCellValue` method to get the value of a cell +* `calculateFormula` method to calculate a formula +* `getCellFormula` method to retrieve a formula from a cell From 8a1d5672e25048bf68f5b1b4980e71fe76c36003 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Wed, 11 Sep 2024 17:10:58 +0200 Subject: [PATCH 03/41] Make HTML+CSS preview work --- docs/.vuepress/config.js | 2 - docs/.vuepress/plugins/examples/examples.js | 228 +++++++----------- .../markdown-it-header-anchor/index.js | 39 --- 3 files changed, 82 insertions(+), 187 deletions(-) delete mode 100644 docs/.vuepress/plugins/markdown-it-header-anchor/index.js diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 1c2973bf99..e9275f8bc0 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -5,7 +5,6 @@ const searchBoxPlugin = require('./plugins/search-box'); const examples = require('./plugins/examples/examples'); const HyperFormula = require('../../dist/hyperformula.full'); const firstHeaderInjection = require('./plugins/markdown-it-header-injection'); -const headerAnchor = require('./plugins/markdown-it-header-anchor'); const conditionalContainer = require('./plugins/markdown-it-conditional-container'); const includeCodeSnippet = require('./plugins/markdown-it-include-code-snippet'); const fs = require('fs'); @@ -118,7 +117,6 @@ module.exports = { md.use(includeCodeSnippet) md.use(conditionalContainer) md.use(firstHeaderInjection) - md.use(headerAnchor) } }, // TODO: It doesn't work. It's seems that this option is bugged. Documentation says that this option is configurable, diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js index d17b7e4dde..cae35d2850 100644 --- a/docs/.vuepress/plugins/examples/examples.js +++ b/docs/.vuepress/plugins/examples/examples.js @@ -94,154 +94,90 @@ module.exports = function(docsVersion, base) { const token = tokens[index]; const m = token.info.trim().match(EXAMPLE_REGEX); - if (token.nesting === 1 && m) { - // open preview - let [, , id, klass, preset, args] = m; - - id = id ? id.substring(1) : 'example1'; - klass = klass ? klass.substring(1) : ''; - preset = preset ? preset.substring(1) : 'hot'; - args = args || ''; - - const htmlPos = args.match(/--html (\d*)/)?.[1]; - const htmlIndex = htmlPos ? index + Number.parseInt(htmlPos, 10) : 0; - const htmlToken = htmlPos ? tokens[htmlIndex] : undefined; - const htmlContent = htmlToken - ? htmlToken.content - : `
`; - const htmlContentRoot = `
${htmlContent}
`; - - const cssPos = args.match(/--css (\d*)/)?.[1]; - const cssIndex = cssPos ? index + Number.parseInt(cssPos, 10) : 0; - const cssToken = cssPos ? tokens[cssIndex] : undefined; - const cssContent = cssToken ? cssToken.content : ''; - - const jsPos = args.match(/--js (\d*)/)?.[1] || 1; - const jsIndex = jsPos ? index + Number.parseInt(jsPos, 10) : 0; - const jsToken = jsPos ? tokens[jsIndex] : undefined; - - const tsPos = args.match(/--ts (\d*)/)?.[1]; - const tsIndex = tsPos ? index + Number.parseInt(tsPos, 10) : 0; - const tsToken = tsPos ? tokens[tsIndex] : undefined; - - // Parse code - // const jsTokenWithBasePath = jsToken?.content?.replaceAll('{{$basePath}}', base); - // const tsTokenWithBasePath = tsToken?.content?.replaceAll('{{$basePath}}', base); - // const codeToCompile = parseCode(jsTokenWithBasePath); - // const tsCodeToCompile = parseCode(tsTokenWithBasePath); - // const codeToCompileSandbox = parseCodeSandbox(jsTokenWithBasePath); - // const tsCodeToCompileSandbox = parseCodeSandbox(tsTokenWithBasePath); - // const codeToPreview = parsePreview(jsTokenWithBasePath); - // const tsCodeToPreview = parsePreview(tsTokenWithBasePath); - - // Replace token content - // if (jsToken) jsToken.content = codeToPreview; - - // if (tsToken) tsToken.content = tsCodeToPreview; - - [htmlIndex, jsIndex, tsIndex, cssIndex].filter(x => !!x).sort().reverse().forEach((x) => { - tokens.splice(x, 1); - }); - - const newTokens = [ - new Token('container_div_open', 'div', 1), - new Token('container_div_close', 'div', -1), - new Token('container_div_open', 'div', 1), - new Token('container_div_close', 'div', -1), - ]; - - tokens.splice(index + 1, 0, ...newTokens); - - // const codeForPreset = addCodeForPreset(codeToCompile, preset, id); - // const tsCodeForPreset = addCodeForPreset(tsCodeToCompile, preset, id); - // const code = buildCode( - // id + (preset.includes('angular') ? '.ts' : '.jsx'), - // codeForPreset, - // env.relativePath - // ); - // const encodedCode = encodeURI( - // `useHandsontable('${docsVersion}', function(){${code}}, '${preset}')` - // ); - const activeTab = `${args.match(/--tab (code|html|css|preview)/)?.[1] ?? 'preview'}-tab-${id}`; - const noEdit = !!args.match(/--no-edit/)?.[0]; - // const isRTL = /layoutDirection(.*)'rtl'/.test(codeToCompile) || /dir="rtl"/.test(htmlContent); - const isActive = `$parent.$parent.isScriptLoaderActivated('${id}')`; - const selectedLang = '$parent.$parent.selectedLang'; - const isJavaScript = preset.includes('hot'); - const isReact = preset.includes('react'); - const isReactOrJavaScript = isJavaScript || isReact; - - return ''; - return ` -
- -
-
-
- - - -
-
- ${!true - ? stackblitz( - id, - htmlContent, - codeToCompileSandbox, - cssContent, - docsVersion, - preset, - 'JavaScript' - ) - : ''} -
-
- ${!true - ? stackblitz( - id, - htmlContent, - tsCodeToCompileSandbox, - cssContent, - docsVersion, - preset, - 'TypeScript' - ) - : ''} -
- - - -
-
-
- - `; - } else { - // close preview + if (token.nesting !== 1 || !m) { return ''; - return '
'; } + + let [, , id, klass, preset, args] = m; + + id = id ? id.substring(1) : 'example1'; + klass = klass ? klass.substring(1) : ''; + preset = preset ? preset.substring(1) : 'hot'; + args = args || ''; + + const htmlPos = args.match(/--html (\d*)/)?.[1]; + const htmlIndex = htmlPos ? index + Number.parseInt(htmlPos, 10) : 0; + const htmlToken = htmlPos ? tokens[htmlIndex] : undefined; + const htmlContent = htmlToken + ? htmlToken.content + : `
`; + const htmlContentRoot = `
${htmlContent}
`; + + const cssPos = args.match(/--css (\d*)/)?.[1]; + const cssIndex = cssPos ? index + Number.parseInt(cssPos, 10) : 0; + const cssToken = cssPos ? tokens[cssIndex] : undefined; + const cssContent = cssToken ? cssToken.content : ''; + + const jsPos = args.match(/--js (\d*)/)?.[1] || 1; + const jsIndex = jsPos ? index + Number.parseInt(jsPos, 10) : 0; + const jsToken = jsPos ? tokens[jsIndex] : undefined; + + const tsPos = args.match(/--ts (\d*)/)?.[1]; + const tsIndex = tsPos ? index + Number.parseInt(tsPos, 10) : 0; + const tsToken = tsPos ? tokens[tsIndex] : undefined; + + // Parse code + const jsTokenWithBasePath = jsToken?.content?.replaceAll('{{$basePath}}', base); + const tsTokenWithBasePath = tsToken?.content?.replaceAll('{{$basePath}}', base); + const codeToCompile = parseCode(jsTokenWithBasePath); + const tsCodeToCompile = parseCode(tsTokenWithBasePath); + const codeToCompileSandbox = parseCodeSandbox(jsTokenWithBasePath); + const tsCodeToCompileSandbox = parseCodeSandbox(tsTokenWithBasePath); + const codeToPreview = parsePreview(jsTokenWithBasePath); + const tsCodeToPreview = parsePreview(tsTokenWithBasePath); + + // Replace token content + if (jsToken) jsToken.content = codeToPreview; + + if (tsToken) tsToken.content = tsCodeToPreview; + + [htmlIndex, jsIndex, tsIndex, cssIndex].filter(x => !!x).sort().reverse().forEach((x) => { + tokens.splice(x, 1); + }); + + const newTokens = [ + new Token('container_div_open', 'div', 1), + new Token('container_div_close', 'div', -1), + new Token('container_div_open', 'div', 1), + new Token('container_div_close', 'div', -1), + ]; + + tokens.splice(index + 1, 0, ...newTokens); + + const codeForPreset = addCodeForPreset(codeToCompile, preset, id); + const tsCodeForPreset = addCodeForPreset(tsCodeToCompile, preset, id); + const code = buildCode( + id + (preset.includes('angular') ? '.ts' : '.jsx'), + codeForPreset, + env.relativePath + ); + const encodedCode = encodeURI( + `useHandsontable('${docsVersion}', function(){${code}}, '${preset}')` + ); + const activeTab = `${args.match(/--tab (code|html|css|preview)/)?.[1] ?? 'preview'}-tab-${id}`; + const noEdit = !!args.match(/--no-edit/)?.[0]; + const selectedLang = '$parent.$parent.selectedLang'; + const isJavaScript = preset.includes('hot'); + const isReact = preset.includes('react'); + const isReactOrJavaScript = isJavaScript || isReact; + + return ` +
+ +
${htmlContentRoot}
+ +
+ `; }, }; }; diff --git a/docs/.vuepress/plugins/markdown-it-header-anchor/index.js b/docs/.vuepress/plugins/markdown-it-header-anchor/index.js deleted file mode 100644 index 00188bdbdd..0000000000 --- a/docs/.vuepress/plugins/markdown-it-header-anchor/index.js +++ /dev/null @@ -1,39 +0,0 @@ -module.exports = function headerAnchor(markdown) { - const insertedTokenTag = 'a'; - const insertedOpenTokenType = 'link_open'; - const insertedCloseTokenType = 'link_close'; - const foundTokenTags = ['h1', 'h2', 'h3']; - const foundOpenTokenType = 'heading_open'; - - const findAndReplace = (state) => { - const Token = state.Token; - const relativePath = state.env?.relativePath; // Sometimes the `env` key is an empty object. - - if (relativePath === void 0) { - return; - } - - state.tokens.forEach((token, index) => { - // Check if token is inside `h` tag - if ( - token.type === 'inline' - && state.tokens[index - 1].type === foundOpenTokenType - && foundTokenTags.includes(state.tokens[index - 1].tag) - ) { - // Create `a` tag with href attribute - const aTagOpen = new Token(insertedOpenTokenType, insertedTokenTag, 1); - const aTagClose = new Token(insertedCloseTokenType, insertedTokenTag, -1); - const id = state.tokens[index - 1].attrGet('id'); - - aTagOpen.attrSet('href', `#${id}`); - aTagOpen.attrSet('class', 'header-link'); - - // Wrap `h` tag content with `a` tag - token.children.unshift(aTagOpen); - token.children.push(aTagClose); - } - }); - }; - - markdown.core.ruler.push('header_anchor', findAndReplace); -}; From 8365cc52a454806fdcd003f6c8ec7b31095bc0c9 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Wed, 11 Sep 2024 17:18:49 +0200 Subject: [PATCH 04/41] Make some of the buttons work --- docs/.vuepress/plugins/examples/examples.js | 50 ++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js index cae35d2850..bc46db7d26 100644 --- a/docs/.vuepress/plugins/examples/examples.js +++ b/docs/.vuepress/plugins/examples/examples.js @@ -165,7 +165,7 @@ module.exports = function(docsVersion, base) { `useHandsontable('${docsVersion}', function(){${code}}, '${preset}')` ); const activeTab = `${args.match(/--tab (code|html|css|preview)/)?.[1] ?? 'preview'}-tab-${id}`; - const noEdit = !!args.match(/--no-edit/)?.[0]; + const noEdit = true; //!!args.match(/--no-edit/)?.[0]; const selectedLang = '$parent.$parent.selectedLang'; const isJavaScript = preset.includes('hot'); const isReact = preset.includes('react'); @@ -177,6 +177,54 @@ module.exports = function(docsVersion, base) {
${htmlContentRoot}
+
+
+ +
+
+ ${!noEdit ? stackblitz( + id, + htmlContent, + codeToCompileSandbox, + cssContent, + docsVersion, + preset, + 'JavaScript' + ) : ''} +
+
+ ${!noEdit ? stackblitz( + id, + htmlContent, + tsCodeToCompileSandbox, + cssContent, + docsVersion, + preset, + 'TypeScript' + ) : ''} +
+ + + +
+
+
`; }, }; From cd5774161ade6aeb73e1f03d42804b59b1eea856 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 12 Sep 2024 13:45:32 +0200 Subject: [PATCH 05/41] Add edit-in-stackblitz button --- docs/.vuepress/plugins/examples/examples.js | 128 ++------------------ 1 file changed, 11 insertions(+), 117 deletions(-) diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js index bc46db7d26..7869c8c311 100644 --- a/docs/.vuepress/plugins/examples/examples.js +++ b/docs/.vuepress/plugins/examples/examples.js @@ -9,35 +9,6 @@ const { buildCode } = require('./code-builder'); const { addCodeForPreset } = require('./add-code-for-preset'); const { stackblitz } = require('./stackblitz'); -const tab = (tabName, token, id) => { - if (!token) return []; - - const openTSDivToken = new Token('html_block', '', 1); - const closeDivToken = new Token('html_block', '', -1); - - openTSDivToken.content = ``; - closeDivToken.content = ''; - - return [ - openTSDivToken, - token, - closeDivToken - ]; -}; - -const parsePreview = (content) => { - if (!content) return ''; - - return content - // Remove the all "/* start:skip-in-compilation */" and "/* end:skip-in-compilation */" comments - .replace(/\/\*(\s+)?(start|end):skip-in-compilation(\s+)?\*\/\n/gm, '') - // Remove the code between "/* start:skip-in-preview */" and "/* end:skip-in-preview */" expressions - .replace(/\/\*(\s+)?start:skip-in-preview(\s+)?\*\/\n.*?\/\*(\s+)?end:skip-in-preview(\s+)?\*\/\n/msg, '') - // Remove /* end-file */ - .replace(/\/\* end-file \*\//gm, '') - .trim(); -}; - const parseCode = (content) => { if (!content) return ''; @@ -61,32 +32,6 @@ const parseCodeSandbox = (content) => { .replace(/\/\*(\s+)?(start|end):skip-in-compilation(\s+)?\*\/\n/gm, ''); }; -const getCodeToken = (jsToken, tsToken) => { - const code = new Token('inline', '', 1); - const openJSDivToken = new Token('container_div_open', 'div', 1); - const openTSDivToken = new Token('container_div_open', 'div', 1); - const closeDivToken = new Token('container_div_close', 'div', -1); - - openJSDivToken.attrSet('class', 'tab-content-js'); - openJSDivToken.attrSet('v-if', '$parent.$parent.selectedLang === \'JavaScript\''); - openTSDivToken.attrSet('class', 'tab-content-ts'); - openTSDivToken.attrSet('v-if', '$parent.$parent.selectedLang === \'TypeScript\''); - - code.children = [ - openJSDivToken, - jsToken, - closeDivToken - ]; - - if (tsToken) { - code.children.push(openTSDivToken); - code.children.push(tsToken); - code.children.push(closeDivToken); - } - - return code; -}; - module.exports = function(docsVersion, base) { return { type: 'example', @@ -130,16 +75,7 @@ module.exports = function(docsVersion, base) { const jsTokenWithBasePath = jsToken?.content?.replaceAll('{{$basePath}}', base); const tsTokenWithBasePath = tsToken?.content?.replaceAll('{{$basePath}}', base); const codeToCompile = parseCode(jsTokenWithBasePath); - const tsCodeToCompile = parseCode(tsTokenWithBasePath); - const codeToCompileSandbox = parseCodeSandbox(jsTokenWithBasePath); const tsCodeToCompileSandbox = parseCodeSandbox(tsTokenWithBasePath); - const codeToPreview = parsePreview(jsTokenWithBasePath); - const tsCodeToPreview = parsePreview(tsTokenWithBasePath); - - // Replace token content - if (jsToken) jsToken.content = codeToPreview; - - if (tsToken) tsToken.content = tsCodeToPreview; [htmlIndex, jsIndex, tsIndex, cssIndex].filter(x => !!x).sort().reverse().forEach((x) => { tokens.splice(x, 1); @@ -155,7 +91,6 @@ module.exports = function(docsVersion, base) { tokens.splice(index + 1, 0, ...newTokens); const codeForPreset = addCodeForPreset(codeToCompile, preset, id); - const tsCodeForPreset = addCodeForPreset(tsCodeToCompile, preset, id); const code = buildCode( id + (preset.includes('angular') ? '.ts' : '.jsx'), codeForPreset, @@ -164,12 +99,6 @@ module.exports = function(docsVersion, base) { const encodedCode = encodeURI( `useHandsontable('${docsVersion}', function(){${code}}, '${preset}')` ); - const activeTab = `${args.match(/--tab (code|html|css|preview)/)?.[1] ?? 'preview'}-tab-${id}`; - const noEdit = true; //!!args.match(/--no-edit/)?.[0]; - const selectedLang = '$parent.$parent.selectedLang'; - const isJavaScript = preset.includes('hot'); - const isReact = preset.includes('react'); - const isReactOrJavaScript = isJavaScript || isReact; return `
@@ -177,52 +106,17 @@ module.exports = function(docsVersion, base) {
${htmlContentRoot}
-
-
- -
-
- ${!noEdit ? stackblitz( - id, - htmlContent, - codeToCompileSandbox, - cssContent, - docsVersion, - preset, - 'JavaScript' - ) : ''} -
-
- ${!noEdit ? stackblitz( - id, - htmlContent, - tsCodeToCompileSandbox, - cssContent, - docsVersion, - preset, - 'TypeScript' - ) : ''} -
- - - -
+
+
+ ${stackblitz( + id, + htmlContent, + tsCodeToCompileSandbox, + cssContent, + docsVersion, + preset, + 'TypeScript' + )}
`; From 58d203f7d8eddd2e3c3d3b2ebffc3958e59c0b50 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 12 Sep 2024 14:33:14 +0200 Subject: [PATCH 06/41] Make the entire runtime of the demo work (including js) --- docs/.vuepress/plugins/examples/examples.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js index 7869c8c311..9655385b75 100644 --- a/docs/.vuepress/plugins/examples/examples.js +++ b/docs/.vuepress/plugins/examples/examples.js @@ -96,15 +96,13 @@ module.exports = function(docsVersion, base) { codeForPreset, env.relativePath ); - const encodedCode = encodeURI( - `useHandsontable('${docsVersion}', function(){${code}}, '${preset}')` - ); + const encodedCode = encodeURI(code); return `
${htmlContentRoot}
- +
From 402c2a4c34715468523d8b702b1afff235c173ee Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 12 Sep 2024 15:21:59 +0200 Subject: [PATCH 07/41] Add real HF demo. Currently failing to load HF --- docs/.vuepress/plugins/examples/examples.js | 5 + docs/examples/demo/example1.css | 73 +++++++++- docs/examples/demo/example1.html | 29 +++- docs/examples/demo/example1.js | 146 +++++++++++++++++++- docs/examples/demo/example1.ts | 146 +++++++++++++++++++- 5 files changed, 386 insertions(+), 13 deletions(-) diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js index 9655385b75..803fdfad84 100644 --- a/docs/.vuepress/plugins/examples/examples.js +++ b/docs/.vuepress/plugins/examples/examples.js @@ -121,3 +121,8 @@ module.exports = function(docsVersion, base) { }, }; }; + +// - use HF in demo +// - remove non-needed glue-code +// - runtime requires js, stackblitz should be in ts, so we need the converter script from HOT as well +// - all demos need to be reworked to the 3-file format \ No newline at end of file diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css index ec2e4fd974..a2012403d1 100644 --- a/docs/examples/demo/example1.css +++ b/docs/examples/demo/example1.css @@ -1,5 +1,68 @@ -h3.demo-preview { - margin-bottom: 0.3rem !important; - padding-top: 0 !important; - margin-top: 0.5rem !important; -} \ No newline at end of file +.example button.run { + background-color: #1c49e4; + border-color: #1c49e4; + margin-bottom: 20px; +} + +.example button.run:hover { + background-color: #2350ea; +} + +.example button.button.reset { + border-color: #1c49e4; + color: #1c49e4; + margin-bottom: 20px; +} + +table tbody tr:last-child { + font-weight: 600; +} + +table tbody tr:last-child td:first-child { + text-align: right; +} + +table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +table { + table-layout: fixed; + font-size: 14px; +} + +table thead tr th:first-child { + padding-left: 40px; +} + +table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +table tbody tr td:first-child span::before { + counter-increment: row-counter; + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +table tbody tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/docs/examples/demo/example1.html b/docs/examples/demo/example1.html index 178511d36e..e748545cd4 100644 --- a/docs/examples/demo/example1.html +++ b/docs/examples/demo/example1.html @@ -1,2 +1,27 @@ -

Hello

-
+
+ + + + + + + + + + + + + + + + + + + + +
NameYear_1Year_2AverageSum
+
\ No newline at end of file diff --git a/docs/examples/demo/example1.js b/docs/examples/demo/example1.js index 3231c55b72..7536af8bad 100644 --- a/docs/examples/demo/example1.js +++ b/docs/examples/demo/example1.js @@ -1,4 +1,144 @@ -// import { HyperFormula } from 'hyperformula'; +import HyperFormula from 'hyperformula'; +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); -const container = document.querySelector('#container'); - container.innerHTML = 'world!'; +/** + * Initial table data. + */ +const tableData = [ + ["Greg Black", 4.66, "=B1*1.3", "=AVERAGE(B1:C1)", "=SUM(B1:C1)"], + ["Anne Carpenter", 5.25, "=$B$2*30%", "=AVERAGE(B2:C2)", "=SUM(B2:C2)"], + ["Natalie Dem", 3.59, "=B3*2.7+2+1", "=AVERAGE(B3:C3)", "=SUM(B3:C3)"], + ["John Sieg", 12.51, "=B4*(1.22+1)", "=AVERAGE(B4:C4)", "=SUM(B4:C4)"], + [ + "Chris Aklips", + 7.63, + "=B5*1.1*SUM(10,20)+1", + "=AVERAGE(B5:C5)", + "=SUM(B5:C5)" + ] +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData +); + +// Add named expressions for the "TOTAL" row. +hf.addNamedExpression("Year_1", "=SUM(main!$B$1:main!$B$5)"); +hf.addNamedExpression("Year_2", "=SUM(main!$C$1:main!$C$5)"); + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector("#run"); + const resetButton = document.querySelector("#reset"); + + runButton.addEventListener("click", () => { + runCalculations(hf, sheetId); + }); + + resetButton.addEventListener("click", () => { + resetTable(tableData); + }); +} + +const ANIMATION_ENABLED = true; + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const totals = ["=SUM(Year_1)", "=SUM(Year_2)"]; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + let totalRowsHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = ""; + + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + + if (!isNaN(cellValue)) { + cellValue = cellValue.toFixed(2); + } + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ""; + } + + totalRowsHTML = ` +TOTAL + + ${ + calculated + ? hf.calculateFormula(totals[0], sheetId).toFixed(2) + : totals[0] + } + + + ${ + calculated + ? hf.calculateFormula(totals[1], sheetId).toFixed(2) + : totals[1] + } + + +`; + + newTbodyHTML += totalRowsHTML; + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Replace formulas with their results. + */ +function runCalculations() { + renderTable(true); +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); diff --git a/docs/examples/demo/example1.ts b/docs/examples/demo/example1.ts index 4cfc7aae91..7536af8bad 100644 --- a/docs/examples/demo/example1.ts +++ b/docs/examples/demo/example1.ts @@ -1,4 +1,144 @@ -// import { HyperFormula } from 'hyperformula'; +import HyperFormula from 'hyperformula'; +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); -const container = document.querySelector('#container')! -container.innerHTML = 'world!' +/** + * Initial table data. + */ +const tableData = [ + ["Greg Black", 4.66, "=B1*1.3", "=AVERAGE(B1:C1)", "=SUM(B1:C1)"], + ["Anne Carpenter", 5.25, "=$B$2*30%", "=AVERAGE(B2:C2)", "=SUM(B2:C2)"], + ["Natalie Dem", 3.59, "=B3*2.7+2+1", "=AVERAGE(B3:C3)", "=SUM(B3:C3)"], + ["John Sieg", 12.51, "=B4*(1.22+1)", "=AVERAGE(B4:C4)", "=SUM(B4:C4)"], + [ + "Chris Aklips", + 7.63, + "=B5*1.1*SUM(10,20)+1", + "=AVERAGE(B5:C5)", + "=SUM(B5:C5)" + ] +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData +); + +// Add named expressions for the "TOTAL" row. +hf.addNamedExpression("Year_1", "=SUM(main!$B$1:main!$B$5)"); +hf.addNamedExpression("Year_2", "=SUM(main!$C$1:main!$C$5)"); + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector("#run"); + const resetButton = document.querySelector("#reset"); + + runButton.addEventListener("click", () => { + runCalculations(hf, sheetId); + }); + + resetButton.addEventListener("click", () => { + resetTable(tableData); + }); +} + +const ANIMATION_ENABLED = true; + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const totals = ["=SUM(Year_1)", "=SUM(Year_2)"]; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + let totalRowsHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = ""; + + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + + if (!isNaN(cellValue)) { + cellValue = cellValue.toFixed(2); + } + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ""; + } + + totalRowsHTML = ` +TOTAL + + ${ + calculated + ? hf.calculateFormula(totals[0], sheetId).toFixed(2) + : totals[0] + } + + + ${ + calculated + ? hf.calculateFormula(totals[1], sheetId).toFixed(2) + : totals[1] + } + + +`; + + newTbodyHTML += totalRowsHTML; + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Replace formulas with their results. + */ +function runCalculations() { + renderTable(true); +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); From f5045bc8c1027289827e9bbd3c6022ba42e18361 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Wed, 18 Sep 2024 16:09:29 +0200 Subject: [PATCH 08/41] Make HyperFormula import work in runtime of the docs examples --- docs/.vuepress/config.js | 11 ++++++----- docs/examples/demo/example1.js | 3 +++ docs/examples/demo/example1.ts | 3 +++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index e9275f8bc0..cad0541452 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -16,6 +16,7 @@ module.exports = { title: 'HyperFormula (v' + HyperFormula.version + ')', description: 'HyperFormula is an open-source, high-performance calculation engine for spreadsheets and web applications.', head: [ + [ 'script', { src: 'https://cdn.jsdelivr.net/npm/hyperformula/dist/hyperformula.full.min.js' } ], // Google Tag Manager, an extra element within the `ssr.html` file. ['script', {}, ` (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': @@ -45,11 +46,11 @@ module.exports = { `], [ 'script', - { - id: 'Sentry.io', - src: 'https://js.sentry-cdn.com/50617701901516ce348cb7b252564a60.min.js', - crossorigin: 'anonymous', - }, + { + id: 'Sentry.io', + src: 'https://js.sentry-cdn.com/50617701901516ce348cb7b252564a60.min.js', + crossorigin: 'anonymous', + }, ], // Favicon ['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/favicon/apple-touch-icon.png' }], diff --git a/docs/examples/demo/example1.js b/docs/examples/demo/example1.js index 7536af8bad..fabfae2442 100644 --- a/docs/examples/demo/example1.js +++ b/docs/examples/demo/example1.js @@ -1,4 +1,7 @@ +/* start:skip-in-compilation */ import HyperFormula from 'hyperformula'; +/* end:skip-in-compilation */ + console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); /** diff --git a/docs/examples/demo/example1.ts b/docs/examples/demo/example1.ts index 7536af8bad..fabfae2442 100644 --- a/docs/examples/demo/example1.ts +++ b/docs/examples/demo/example1.ts @@ -1,4 +1,7 @@ +/* start:skip-in-compilation */ import HyperFormula from 'hyperformula'; +/* end:skip-in-compilation */ + console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); /** From e0a45aea5b605d79d19081e4462f91fc27111b55 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Mon, 23 Sep 2024 18:59:34 +0200 Subject: [PATCH 09/41] Add script code-examples-generator --- docs/.vuepress/plugins/examples/examples.js | 4 +- docs/code-examples-generator.sh | 108 ++++++++++++++++++++ docs/examples/demo/example1.js | 72 ++++++------- docs/examples/eslintrc.examples.js | 60 +++++++++++ package-lock.json | 54 +++++++++- package.json | 5 + 6 files changed, 260 insertions(+), 43 deletions(-) create mode 100644 docs/code-examples-generator.sh create mode 100644 docs/examples/eslintrc.examples.js diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js index 803fdfad84..c0ce8977b1 100644 --- a/docs/.vuepress/plugins/examples/examples.js +++ b/docs/.vuepress/plugins/examples/examples.js @@ -122,7 +122,5 @@ module.exports = function(docsVersion, base) { }; }; -// - use HF in demo +// - all demos need to be reworked to the 3-file format // - remove non-needed glue-code -// - runtime requires js, stackblitz should be in ts, so we need the converter script from HOT as well -// - all demos need to be reworked to the 3-file format \ No newline at end of file diff --git a/docs/code-examples-generator.sh b/docs/code-examples-generator.sh new file mode 100644 index 0000000000..ecd1da3adc --- /dev/null +++ b/docs/code-examples-generator.sh @@ -0,0 +1,108 @@ +#!/usr/bin/bash + +# This script generates JS/JSX examples from TS/TSX files and formats them using ESLint. +# Usage: +# ./code-examples-generator.sh path/to/file.ts - generates single example path/to/file.js +# ./code-examples-generator.sh --generateAll - generates all examples in the content/guides directory +# ./code-examples-generator.sh --formatAllTsExamples - runs the autoformatter on all TS and TSX example files in the content/guides directory + +ALL_EXAMPLES_DIR="docs/examples" +ESLINT_CONFIG="docs/examples/eslintrc.examples.js" + +format() { + eslint --fix --no-ignore -c "$ESLINT_CONFIG" "$1" > /dev/null +} + +build_output_filename() { + local input_filename + local output_filename + input_filename="$1" + + if [[ "$input_filename" == *.ts ]]; then + output_filename="${input_filename%.*}.js" + elif [[ "$input_filename" == *.tsx ]]; then + output_filename="${input_filename%.*}.jsx" + else + echo "Invalid file extension: $input_filename. Must be .ts or .tsx" >&2 + return 1 + fi + + echo "$output_filename" +} + +generate() { + local input_filename + local output_filename + input_filename="$1" + output_filename=$(build_output_filename "$input_filename") + + if [[ "$input_filename" == *.ts ]]; then + tsc --target esnext --skipLibCheck "$input_filename" > /dev/null + elif [[ "$input_filename" == *.tsx ]]; then + tsc --target esnext --jsx preserve --skipLibCheck "$input_filename" > /dev/null + else + echo "Invalid file extension: $input_filename. Must be .ts or .tsx" >&2 + return 1 + fi + + if [ ! -f "$output_filename" ]; then + echo "Failed to generate $output_filename from $input_filename" >&2 + return 1 + fi +} + +format_single_file() { + format "$1" + echo "Formatted $1" +} + +generate_single_example() { + local input_filename + local output_filename + input_filename="$1" + output_filename=$(build_output_filename "$input_filename") + + generate "$input_filename" + format "$output_filename" + echo "Generated $output_filename" +} + +go_through_all_examples_concurrently() { + local task + local jobs_limit + task="$1" + jobs_limit=16 + + echo "Running $jobs_limit jobs in parallel..." + + find "$ALL_EXAMPLES_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -print0 | while read -d $'\0' source_input_filename; do + while test "$(jobs | wc -l)" -ge "$jobs_limit"; do + sleep 1 + done + + if [ "$task" == "formatAllTsExamples" ]; then + format_single_file "$source_input_filename" & + else + generate_single_example "$source_input_filename" & + fi + + done + + wait + echo "Waiting for the result of all jobs..." + sleep 20 + echo "All jobs finished" +} + +if [ -z "$1" ]; then + echo "Provide a path to the TS/TSX file or use one of the commands: --generateAll, --formatAllTsExamples" +elif [ "$1" == "--generateAll" ]; then + echo "Generating all examples..." + go_through_all_examples_concurrently "generateAll" +elif [ "$1" == "--formatAllTsExamples" ]; then + echo "Formatting all TS/TSX example files..." + go_through_all_examples_concurrently "formatAllTsExamples" +else + echo "Generating single example..." + generate_single_example "$1" +fi diff --git a/docs/examples/demo/example1.js b/docs/examples/demo/example1.js index fabfae2442..63fd56326d 100644 --- a/docs/examples/demo/example1.js +++ b/docs/examples/demo/example1.js @@ -1,33 +1,36 @@ /* start:skip-in-compilation */ import HyperFormula from 'hyperformula'; -/* end:skip-in-compilation */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +/* end:skip-in-compilation */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); /** * Initial table data. */ const tableData = [ - ["Greg Black", 4.66, "=B1*1.3", "=AVERAGE(B1:C1)", "=SUM(B1:C1)"], - ["Anne Carpenter", 5.25, "=$B$2*30%", "=AVERAGE(B2:C2)", "=SUM(B2:C2)"], - ["Natalie Dem", 3.59, "=B3*2.7+2+1", "=AVERAGE(B3:C3)", "=SUM(B3:C3)"], - ["John Sieg", 12.51, "=B4*(1.22+1)", "=AVERAGE(B4:C4)", "=SUM(B4:C4)"], + ['Greg Black', 4.66, '=B1*1.3', '=AVERAGE(B1:C1)', '=SUM(B1:C1)'], + ['Anne Carpenter', 5.25, '=$B$2*30%', '=AVERAGE(B2:C2)', '=SUM(B2:C2)'], + ['Natalie Dem', 3.59, '=B3*2.7+2+1', '=AVERAGE(B3:C3)', '=SUM(B3:C3)'], + ['John Sieg', 12.51, '=B4*(1.22+1)', '=AVERAGE(B4:C4)', '=SUM(B4:C4)'], [ - "Chris Aklips", + 'Chris Aklips', 7.63, - "=B5*1.1*SUM(10,20)+1", - "=AVERAGE(B5:C5)", - "=SUM(B5:C5)" - ] + '=B5*1.1*SUM(10,20)+1', + '=AVERAGE(B5:C5)', + '=SUM(B5:C5)', + ], ]; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ - licenseKey: "gpl-v3" + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. @@ -35,27 +38,25 @@ hf.setCellContents( { row: 0, col: 0, - sheet: sheetId + sheet: sheetId, }, tableData ); - // Add named expressions for the "TOTAL" row. -hf.addNamedExpression("Year_1", "=SUM(main!$B$1:main!$B$5)"); -hf.addNamedExpression("Year_2", "=SUM(main!$C$1:main!$C$5)"); +hf.addNamedExpression('Year_1', '=SUM(main!$B$1:main!$B$5)'); +hf.addNamedExpression('Year_2', '=SUM(main!$C$1:main!$C$5)'); /** * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector("#run"); - const resetButton = document.querySelector("#reset"); + const runButton = document.querySelector('#run'); + const resetButton = document.querySelector('#reset'); - runButton.addEventListener("click", () => { + runButton.addEventListener('click', () => { runCalculations(hf, sheetId); }); - - resetButton.addEventListener("click", () => { + resetButton.addEventListener('click', () => { resetTable(tableData); }); } @@ -68,19 +69,19 @@ const ANIMATION_ENABLED = true; * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. */ function renderTable(calculated = false) { - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; - const totals = ["=SUM(Year_1)", "=SUM(Year_2)"]; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const totals = ['=SUM(Year_1)', '=SUM(Year_2)']; const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; - let totalRowsHTML = ""; + let newTbodyHTML = ''; + let totalRowsHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = calculated || !cellHasFormula; - let cellValue = ""; + let cellValue = ''; if (!hf.isCellEmpty(cellAddress) && showFormula) { cellValue = hf.getCellValue(cellAddress); @@ -93,36 +94,30 @@ function renderTable(calculated = false) { } newTbodyHTML += ` ${cellValue} `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } totalRowsHTML = ` TOTAL ${ - calculated - ? hf.calculateFormula(totals[0], sheetId).toFixed(2) - : totals[0] + calculated ? hf.calculateFormula(totals[0], sheetId).toFixed(2) : totals[0] } ${ - calculated - ? hf.calculateFormula(totals[1], sheetId).toFixed(2) - : totals[1] + calculated ? hf.calculateFormula(totals[1], sheetId).toFixed(2) : totals[1] } `; - newTbodyHTML += totalRowsHTML; - tbodyDOM.innerHTML = newTbodyHTML; } @@ -142,6 +137,5 @@ function resetTable() { // Bind the button events. bindEvents(); - // Render the table. renderTable(); diff --git a/docs/examples/eslintrc.examples.js b/docs/examples/eslintrc.examples.js new file mode 100644 index 0000000000..aa4f35cb39 --- /dev/null +++ b/docs/examples/eslintrc.examples.js @@ -0,0 +1,60 @@ +const jsdocOff = Object.keys(require('eslint-plugin-jsdoc').rules) + .reduce((acc, rule) => { + acc[`jsdoc/${rule}`] = 'off'; + + return acc; + }, {}); + +module.exports = { + extends: ['../../.eslintrc.js', 'plugin:prettier/recommended'], + parserOptions: { + requireConfigFile: false + }, + rules: { + ...jsdocOff, + "prettier/prettier": [ + "error", + { + "singleQuote": true, + } + ], + 'no-restricted-syntax': 'off', + 'no-restricted-globals': 'off', + 'no-console': 'off', + 'no-await-in-loop': 'off', + 'no-unused-vars': 'off', + 'padding-line-between-statements': [ + 'error', + { blankLine: 'always', prev: '*', next: 'multiline-block-like' }, + { blankLine: 'always', prev: 'multiline-block-like', next: '*' }, + + // { blankLine: "always", prev: "*", next: "multiline-const" }, + { blankLine: 'always', prev: 'multiline-const', next: '*' }, + + // { blankLine: "always", prev: "*", next: "multiline-let" }, + { blankLine: 'always', prev: 'multiline-let', next: '*' }, + + // { blankLine: "always", prev: "*", next: "multiline-var" }, + { blankLine: 'always', prev: 'multiline-var', next: '*' }, + + { blankLine: 'always', prev: ['singleline-const', 'singleline-let', 'singleline-var'], next: '*' }, + { + blankLine: 'any', + prev: ['singleline-const', 'singleline-let', 'singleline-var'], + next: ['const', 'let', 'var'] + }, + + // { blankLine: "always", prev: "*", next: "multiline-expression" }, + { blankLine: 'always', prev: 'multiline-expression', next: '*' }, + + { blankLine: 'always', prev: 'expression', next: '*' }, + { blankLine: 'any', prev: 'expression', next: 'expression' }, + + { blankLine: 'always', prev: 'import', next: '*' }, + { blankLine: 'any', prev: 'import', next: 'import' }, + + { blankLine: 'always', prev: ['case', 'default'], next: '*' }, + { blankLine: 'any', prev: ['case', 'default'], next: ['case', 'default'] } + ] + } +}; diff --git a/package-lock.json b/package-lock.json index dcbe9d3b50..d9c004e701 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,8 +44,10 @@ "cross-env": "^7.0.0", "env-cmd": "^10.1.0", "eslint": "^7.0.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-jsdoc": "^43.1.1", "eslint-plugin-license-header": "^0.6.0", + "eslint-plugin-prettier": "^4.2.1", "full-icu": "^1.3.1", "jasmine": "^4.0.0", "jest": "^26.0.0", @@ -10581,6 +10583,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-plugin-jsdoc": { "version": "43.2.0", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-43.2.0.tgz", @@ -10636,6 +10650,27 @@ "requireindex": "^1.2.0" } }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -11325,6 +11360,12 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -20209,7 +20250,6 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, - "optional": true, "bin": { "prettier": "bin-prettier.js" }, @@ -20220,6 +20260,18 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-error": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", diff --git a/package.json b/package.json index ee79739bbf..0a84f1de7d 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,9 @@ "scripts": { "docs:dev": "npm run typedoc:build-api && cross-env NODE_OPTIONS=--openssl-legacy-provider vuepress dev docs --silent --no-clear-screen --no-cache", "docs:build": "npm run bundle-all && npm run typedoc:build-api && cross-env NODE_OPTIONS=--openssl-legacy-provider vuepress build docs", + "docs:code-examples:generate-js": "bash docs/code-examples-generator.sh", + "docs:code-examples:generate-all-js": "bash docs/code-examples-generator.sh --generateAll", + "docs:code-examples:format-all-ts": "bash docs/code-examples-generator.sh --formatAllTsExamples", "bundle-all": "cross-env HF_COMPILE=1 npm-run-all clean compile bundle:** verify-bundles", "bundle:es": "(node script/if-ne-env.js HF_COMPILE=1 || npm run compile) && cross-env-shell BABEL_ENV=es env-cmd -f ht.config.js babel lib --out-dir es", "bundle:cjs": "(node script/if-ne-env.js HF_COMPILE=1 || npm run compile) && cross-env-shell BABEL_ENV=commonjs env-cmd -f ht.config.js babel lib --out-dir commonjs", @@ -128,8 +131,10 @@ "cross-env": "^7.0.0", "env-cmd": "^10.1.0", "eslint": "^7.0.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-jsdoc": "^43.1.1", "eslint-plugin-license-header": "^0.6.0", + "eslint-plugin-prettier": "^4.2.1", "full-icu": "^1.3.1", "jasmine": "^4.0.0", "jest": "^26.0.0", From 52a0954e6ab1d95c98d872d102463ec9acfd5320 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Wed, 25 Sep 2024 13:12:38 +0200 Subject: [PATCH 10/41] Style stackblitz button --- docs/.vuepress/plugins/examples/examples.js | 22 ++++---- docs/.vuepress/plugins/examples/stackblitz.js | 3 +- docs/.vuepress/styles/index.styl | 52 ++++++++++++++++++- docs/.vuepress/styles/palette.styl | 4 ++ 4 files changed, 67 insertions(+), 14 deletions(-) diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js index c0ce8977b1..76d1867163 100644 --- a/docs/.vuepress/plugins/examples/examples.js +++ b/docs/.vuepress/plugins/examples/examples.js @@ -105,22 +105,20 @@ module.exports = function(docsVersion, base) {
-
- ${stackblitz( - id, - htmlContent, - tsCodeToCompileSandbox, - cssContent, - docsVersion, - preset, - 'TypeScript' - )} -
+ ${stackblitz( + id, + htmlContent, + tsCodeToCompileSandbox, + cssContent, + docsVersion, + preset, + 'TypeScript' + )}
`; }, }; }; -// - all demos need to be reworked to the 3-file format // - remove non-needed glue-code +// - all demos need to be reworked to the 3-file format diff --git a/docs/.vuepress/plugins/examples/stackblitz.js b/docs/.vuepress/plugins/examples/stackblitz.js index c8432b738d..28f4942934 100644 --- a/docs/.vuepress/plugins/examples/stackblitz.js +++ b/docs/.vuepress/plugins/examples/stackblitz.js @@ -39,11 +39,12 @@ const stackblitz = (id, html, js, css, docsVersion, preset, lang) => { diff --git a/docs/.vuepress/styles/index.styl b/docs/.vuepress/styles/index.styl index 0679d6cdbe..ece6a80572 100644 --- a/docs/.vuepress/styles/index.styl +++ b/docs/.vuepress/styles/index.styl @@ -87,4 +87,54 @@ table { line-height: 1.7; text-align: left; } -} \ No newline at end of file +} + +.example-controls { + display: flex + flex-wrap: wrap + gap: 8px + background: $editorColor + border-radius: $radius + padding: 10px + margin 0 + height: 36px + + .hidden { + display: none + } + + button { + border: 1px solid $borderColor + border-radius: $radius + padding: 7px 16px 7px 13px !important + display: flex + align-items: center + gap: 8px + background: white + font-size: 14px + + i, svg { + opacity: .7 + } + + svg { + path { + fill: black + } + } + + &:disabled { + i { + opacity: 0.3 !important + } + } + + @media (hover: hover) { + &:hover { + i, svg { + opacity 1 + } + } + } + } +} diff --git a/docs/.vuepress/styles/palette.styl b/docs/.vuepress/styles/palette.styl index 4b7e0fa3d3..4659740559 100644 --- a/docs/.vuepress/styles/palette.styl +++ b/docs/.vuepress/styles/palette.styl @@ -7,6 +7,7 @@ $arrowBgColor = #ccc $badgeTipColor = #1147f1 $badgeWarningColor = darken(#ffe564, 35%) $badgeErrorColor = #DA5961 +$editorColor = #efeff3 // layout $navbarHeight = 3.6rem @@ -18,3 +19,6 @@ $homePageWidth = 960px $MQNarrow = 959px $MQMobile = 719px $MQMobileNarrow = 419px + +// other +$radius = 8px From f9ea2aa250e913d4137c4331538150dc44b2208b Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 26 Sep 2024 11:28:08 +0200 Subject: [PATCH 11/41] Style demo internal buttons --- docs/.vuepress/styles/index.styl | 1 - docs/examples/demo/example1.css | 60 ++++++++++++++++++++++---------- docs/examples/demo/example1.html | 4 +-- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/docs/.vuepress/styles/index.styl b/docs/.vuepress/styles/index.styl index ece6a80572..27ffd92ef0 100644 --- a/docs/.vuepress/styles/index.styl +++ b/docs/.vuepress/styles/index.styl @@ -97,7 +97,6 @@ table { border-radius: $radius padding: 10px margin 0 - height: 36px .hidden { display: none diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css index a2012403d1..e98e9339f3 100644 --- a/docs/examples/demo/example1.css +++ b/docs/examples/demo/example1.css @@ -1,42 +1,64 @@ -.example button.run { - background-color: #1c49e4; - border-color: #1c49e4; +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 10px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .4em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: 1.1em; + font-weight: 700; + height: 3.8em; + letter-spacing: .1em; + line-height: 3.8em; + padding: 0 3.0em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; margin-bottom: 20px; + background-color: #1c49e4; } -.example button.run:hover { +.example button:hover { background-color: #2350ea; } -.example button.button.reset { - border-color: #1c49e4; +.example button.outline { + background-color: transparent; color: #1c49e4; - margin-bottom: 20px; } -table tbody tr:last-child { +.example table { + table-layout: fixed; + font-size: 14px; +} + +.example table tbody tr:last-child { font-weight: 600; } -table tbody tr:last-child td:first-child { +.example table tbody tr:last-child td:first-child { text-align: right; } -table tbody tr td:first-child { +.example table tbody tr td:first-child { text-align: center; padding: 0; } -table { - table-layout: fixed; - font-size: 14px; -} - -table thead tr th:first-child { +.example table thead tr th:first-child { padding-left: 40px; } -table tbody tr td:first-child span { +.example table tbody tr td:first-child span { width: 100%; display: inline-block; text-align: left; @@ -44,7 +66,7 @@ table tbody tr td:first-child span { margin-left: 0; } -table tbody tr td:first-child span::before { +.example table tbody tr td:first-child span::before { counter-increment: row-counter; content: counter(row-counter); display: inline-block; @@ -53,7 +75,7 @@ table tbody tr td:first-child span::before { left: -10px; } -table tbody tr td.updated-cell span { +.example table tbody tr td.updated-cell span { animation-name: cell-appear; animation-duration: 0.6s; } diff --git a/docs/examples/demo/example1.html b/docs/examples/demo/example1.html index e748545cd4..e318f98704 100644 --- a/docs/examples/demo/example1.html +++ b/docs/examples/demo/example1.html @@ -1,8 +1,8 @@
- - From 8d0216ec685e7f5375aa08ec608315052c2cce2f Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 26 Sep 2024 13:03:21 +0200 Subject: [PATCH 12/41] Remove unused glue-code --- docs/.vuepress/config.js | 13 +- .../plugins/examples/add-code-for-preset.js | 53 ---- .../plugins/examples/buildJavascriptBody.js | 39 +++ .../buildAngularBody.js | 233 ------------------ .../buildJavascriptBody.js | 92 ------- .../code-structure-builder/buildReactBody.js | 207 ---------------- .../code-structure-builder/buildVue3Body.js | 67 ----- .../code-structure-builder/buildVueBody.js | 76 ------ .../code-structure-builder/getBody.js | 42 ---- docs/.vuepress/plugins/examples/examples.js | 33 +-- docs/.vuepress/plugins/examples/stackblitz.js | 31 +-- 11 files changed, 61 insertions(+), 825 deletions(-) delete mode 100644 docs/.vuepress/plugins/examples/add-code-for-preset.js create mode 100644 docs/.vuepress/plugins/examples/buildJavascriptBody.js delete mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/buildAngularBody.js delete mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/buildJavascriptBody.js delete mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/buildReactBody.js delete mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/buildVue3Body.js delete mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/buildVueBody.js delete mode 100644 docs/.vuepress/plugins/examples/code-structure-builder/getBody.js diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index cad0541452..e59df03114 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -7,8 +7,6 @@ const HyperFormula = require('../../dist/hyperformula.full'); const firstHeaderInjection = require('./plugins/markdown-it-header-injection'); const conditionalContainer = require('./plugins/markdown-it-conditional-container'); const includeCodeSnippet = require('./plugins/markdown-it-include-code-snippet'); -const fs = require('fs'); -const path = require('path'); const searchPattern = new RegExp('^/api', 'i'); @@ -16,6 +14,7 @@ module.exports = { title: 'HyperFormula (v' + HyperFormula.version + ')', description: 'HyperFormula is an open-source, high-performance calculation engine for spreadsheets and web applications.', head: [ + // Import HF (required for the examples) [ 'script', { src: 'https://cdn.jsdelivr.net/npm/hyperformula/dist/hyperformula.full.min.js' } ], // Google Tag Manager, an extra element within the `ssr.html` file. ['script', {}, ` @@ -62,15 +61,7 @@ module.exports = { base: '/', plugins: [ searchBoxPlugin, - ['container', examples('1.0.0', 'docs')], - // [ - // 'vuepress-plugin-clean-urls', - // { - // normalSuffix: '', - // indexSuffix: '/', - // notFoundPath: '/404.html', - // }, - // ], + ['container', examples()], { extendPageData ($page) { // inject current HF version as {{ $page.version }} variable diff --git a/docs/.vuepress/plugins/examples/add-code-for-preset.js b/docs/.vuepress/plugins/examples/add-code-for-preset.js deleted file mode 100644 index c5ec28205d..0000000000 --- a/docs/.vuepress/plugins/examples/add-code-for-preset.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Regular expression used to match the export default statement in the code. - * - * @type {RegExp} - */ -const EXPORT_DEFAULT_REGEX = /export default (?:function ([\w]*)|([\w]*))(?:;)/; - -const addCodeForPreset = (code, preset, id) => { - const match = code.match(EXPORT_DEFAULT_REGEX); - const exportId = match?.[1] || match?.[2] || code.includes('export class AppModule'); - - const renderImportPart = () => { - if (/vue3(-.*)?/.test(preset)) { - return 'import { createApp } from \'vue\';'; - } - - return ''; - }; - - const renderCreatePart = () => { - if (/react(-.*)?/.test(preset)) { - return `ReactDOM.render(<${exportId} />, document.getElementById("${id}"));`; - } else if (/vue3(-.*)?/.test(preset)) { - return `const app = createApp(${exportId}); -app.mount('#${id}');`; - } else if (/vue(-.*)?/.test(preset)) { - return `new Vue({ -...${exportId}, -el: '#${id}', -});`; - } else if (/angular(-.*)?/.test(preset)) { - return `import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; - -platformBrowserDynamic() - .bootstrapModule(AppModule) - .catch(err => { console.error(err) });`; - } - - return ''; - }; - - const importPart = renderImportPart(); - const renderPart = renderCreatePart(); - - if (exportId) { - return `${importPart ? `${importPart}\n` : ''}${code}${renderPart ? `\n${renderPart}` : ''}` - .replace(EXPORT_DEFAULT_REGEX, ''); - } - - return code; -}; - -module.exports = { addCodeForPreset }; diff --git a/docs/.vuepress/plugins/examples/buildJavascriptBody.js b/docs/.vuepress/plugins/examples/buildJavascriptBody.js new file mode 100644 index 0000000000..3a79ebb4e8 --- /dev/null +++ b/docs/.vuepress/plugins/examples/buildJavascriptBody.js @@ -0,0 +1,39 @@ +const buildJavascriptBody = ({ id, html, js, css, hyperformulaVersion, lang }) => { + return { + files: { + 'package.json': { + content: `{ + "name": "hyperformula-demo", + "version": "1.0.0", + "description": "", + "dependencies": { + "hyperformula": "${hyperformulaVersion}" + } +}` + }, + 'index.html': { + content: ` + + + + + HyperFormula demo + + + + ${html || `
`} + +` + }, + 'styles.css': { + content: css + }, + [`index.${lang}`]: { + content: `import './styles.css' +${js}` + }, + } + }; +}; + +module.exports = { buildJavascriptBody }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/buildAngularBody.js b/docs/.vuepress/plugins/examples/code-structure-builder/buildAngularBody.js deleted file mode 100644 index 01d8b125d8..0000000000 --- a/docs/.vuepress/plugins/examples/code-structure-builder/buildAngularBody.js +++ /dev/null @@ -1,233 +0,0 @@ -const buildAngularBody = ({ html, js, version, hyperformulaVersion }) => { - const codeParts = js.matchAll(/\/\* file:(.*?)\*\/(.*?)\/\* end-file \*\//gs); - const codePartsObject = [...codeParts]?.reduce((acc, curr) => { - const name = curr?.[1].trim(); - const content = curr?.[2].trim(); - // eslint-disable-next-line - const path = 'src/app/' + name; - - if (name.includes('.ts')) { - acc[path] = { - content - }; - } - - return acc; - }, {}) ?? {}; - - return { - files: { - 'package.json': { - content: `{ - "name": "handsontable", - "version": "1.0.0", - "description": "", - "scripts": { - "ng": "ng", - "start": "ng serve --disable-host-check", - "build": "ng build" - }, - "dependencies": { - "@angular/animations": "^17.3.0", - "@angular/common": "^17.3.0", - "@angular/compiler": "^17.3.0", - "@angular/core": "^17.3.0", - "@angular/forms": "^17.3.0", - "@angular/platform-browser": "^17.3.0", - "@angular/platform-browser-dynamic": "^17.3.0", - "@angular/router": "^17.3.0", - "numbro": "^2.4.0", - "rxjs": "^7.8.0", - "tslib": "^2.6.2", - "zone.js": "^0.14.4", - "hyperformula": "${hyperformulaVersion}", - "handsontable": "${version}", - "@handsontable/angular": "${version}" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^17.3.0", - "@angular/localize": "latest", - "@angular/service-worker": "latest", - "@angular/cli": "^17.3.0", - "@angular/compiler-cli": "^17.3.0", - "@types/node": "12.20.7", - "ts-node": "8.3.0", - "typescript": "5.4.2" - } -}`, - }, - 'angular.json': { - content: `{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "sandbox": { - "projectType": "application", - "schematics": { - "@schematics/angular:application": { - "strict": true - } - }, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:browser", - "options": { - "outputPath": "dist", - "index": "src/index.html", - "main": "src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "tsconfig.app.json", - "styles": [ - "node_modules/handsontable/dist/handsontable.full.css" - ], - "scripts": [], - "preserveSymlinks": true, - "allowedCommonJsDependencies": [ - "core-js", - "@handsontable/pikaday", - "numbro" - ] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "options": { - "browserTarget": "sandbox:build" - }, - "configurations": { - "production": { - "browserTarget": "sandbox:build:production" - }, - "development": { - "browserTarget": "sandbox:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "sandbox:build" - } - } - } - } - }, - "defaultProject": "sandbox", - "cli": { - "analytics": false - } -}`, - }, - 'tsconfig.app.json': { - content: `/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/app", - "types": [] - }, - "files": [ - "src/main.ts" - ], - "include": [ - "src/**/*.d.ts" - ] -}` - }, - 'tsconfig.json': { - content: `/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "compileOnSave": false, - "compilerOptions": { - "baseUrl": "./", - "outDir": "./dist/out-tsc", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "declaration": false, - "downlevelIteration": true, - "experimentalDecorators": true, - "moduleResolution": "node", - "importHelpers": true, - "target": "ES2022", - "module": "ES2022", - "useDefineForClassFields": false, - "lib": [ - "ES2022", - "dom" - ] - }, - "angularCompilerOptions": { - "disableTypeScriptVersionCheck": true, - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -}` - }, - 'src/index.html': { - content: ` - - - - Handsontable for Angular example - - - - - ${html || ''} - -`, - }, - 'src/main.ts': { - content: `import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { AppModule } from './app/app.module'; - -platformBrowserDynamic() - .bootstrapModule(AppModule) - .catch((err) => console.error(err)); -`, - }, - ...codePartsObject - }, - }; -}; - -module.exports = { buildAngularBody }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/buildJavascriptBody.js b/docs/.vuepress/plugins/examples/code-structure-builder/buildJavascriptBody.js deleted file mode 100644 index 7063d249c0..0000000000 --- a/docs/.vuepress/plugins/examples/code-structure-builder/buildJavascriptBody.js +++ /dev/null @@ -1,92 +0,0 @@ -const buildJavascriptBody = ({ id, html, js, css, version, hyperformulaVersion, sandbox, lang }) => { - if (sandbox === 'stackblitz') { - return { - files: { - 'package.json': { - content: `{ - "name": "handsontable", - "version": "1.0.0", - "description": "", - "dependencies": { - "hyperformula": "${hyperformulaVersion}", - "handsontable": "${version}" - } - }` - }, - 'index.html': { - content: ` - - - - - Handsontable - - - - ${html || `
`} - - ` - }, - 'styles.css': { - content: css - }, - [`index.${lang}`]: { - content: `import './styles.css' -${js}` - }, - } - }; - } - - return { - files: { - 'package.json': { - content: `{ - "name": "handsontable", - "version": "1.0.0", - "description": "", - "main": "index.html", - "scripts": { - "start": "parcel --no-source-maps index.html --open", - "build": "parcel build index.html" - }, - "dependencies": { - "hyperformula": "${hyperformulaVersion}", - "handsontable": "${version}" - }, - "devDependencies": { - "@babel/core": "7.2.0", - "parcel-bundler": "^1.6.1" - } -}` - }, - 'index.html': { - content: ` - - - - - Handsontable - - ${js.includes('import { HyperFormula } from \'hyperformula\';') - ? '' - : ''} - - - - ${html || `
`} - - -` - }, - 'src/styles.css': { - content: css - }, - [`src/index.${lang}`]: { - content: js.replace('import { HyperFormula } from \'hyperformula\';', '') - } - } - }; -}; - -module.exports = { buildJavascriptBody }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/buildReactBody.js b/docs/.vuepress/plugins/examples/code-structure-builder/buildReactBody.js deleted file mode 100644 index 1f2ccb4e62..0000000000 --- a/docs/.vuepress/plugins/examples/code-structure-builder/buildReactBody.js +++ /dev/null @@ -1,207 +0,0 @@ -const buildReactBody = ({ js, css, version, hyperformulaVersion, preset, sandbox, lang }) => { - const addReduxDependencies = preset.includes('redux') - ? ` - "redux": "^4.0.0", - "react-redux": "^7.2.4",` - : ''; - - const addAdvancedDependencies = preset.includes('advanced') - ? `"redux": "^4.0.0", - "react-redux": "^7.2.4", - "react-colorful": "5.6.1", - "react-star-rating-component": "1.4.1",` - : ''; - - const tsconfig = lang === 'tsx' ? { - 'tsconfig.json': { - content: `{ - "compilerOptions": { - "target": "es6", - "module": "commonjs", - "moduleResolution": "node", - "noResolve": false, - "noImplicitAny": false, - "allowJs": true, - "jsx": "react", - "skipLibCheck": true, - "lib": [ - "dom", - "es2020" - ] - }, - "exclude": [ - "./node_modules/**/*" - ] -}` - } - } : {}; - - if (sandbox === 'stackblitz') { - return { - files: { - 'package.json': { - content: `{ - "name": "handsontable", - "version": "1.0.0", - "description": "", - "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0",${addReduxDependencies}${addAdvancedDependencies} - "hyperformula": "${hyperformulaVersion}", - "handsontable": "${version}", - "@handsontable/react": "${version}"${lang === 'tsx' ? `, - "@types/react": "18.0.21", - "@types/react-dom": "18.0.6", - "typescript": "5.5.2"` : '' -} - }, - ${lang === 'tsx' ? - `"devDependencies": { - "react-scripts-ts": "latest" - },` : '' -} - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -}` - }, - 'public/index.html': { - content: ` - - - - - Handsontable - - - - -
- - -` - }, - 'src/styles.css': { - content: css - }, - [`src/index.${lang === 'jsx' ? 'js' : 'tsx'}`]: { - content: `import React, { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; -import "./styles.css"; -import ExampleComponent from "./ExampleComponent"; - -const rootElement = document.getElementById("root"); -const root = createRoot(rootElement); - -root.render( - - - -);` - }, - [`src/ExampleComponent.${lang}`]: { - content: `import React from "react"; -${js}` - }, - ...tsconfig - } - }; - } - - return { - files: { - 'package.json': { - content: `{ - "name": "handsontable", - "version": "1.0.0", - "description": "", - "main": "src/index.${lang}", - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build" - }, - "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0",${addReduxDependencies}${addAdvancedDependencies} - "handsontable": "${version}", - "@handsontable/react": "${version}"${lang === 'tsx' ? `, - "@types/react": "18.0.21", - "@types/react-dom": "18.0.6", - "typescript": "5.5.2"` : '' -} - }, - "devDependencies": { - "react-scripts": "^5.0.1" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -}` - }, - 'public/index.html': { - content: ` - - - - - Handsontable - ${js.includes('import { HyperFormula } from \'hyperformula\';') - ? '' - : ''} - - - - -
- - -` - }, - 'src/styles.css': { - content: css - }, - [`src/index.${lang}`]: { - content: `import * as React from "react"; -import { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; -import "./styles.css"; -import ExampleComponent from "./ExampleComponent"; - -const rootElement = document.getElementById("root"); -const root = createRoot(rootElement); - -root.render( - - - -);` - }, - [`src/ExampleComponent.${lang}`]: { - content: `import * as React from "react"; -${js.replace('import { HyperFormula } from \'hyperformula\';', '')}` - }, - ...tsconfig - } - }; - -}; - -module.exports = { buildReactBody }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/buildVue3Body.js b/docs/.vuepress/plugins/examples/code-structure-builder/buildVue3Body.js deleted file mode 100644 index 64812a86e5..0000000000 --- a/docs/.vuepress/plugins/examples/code-structure-builder/buildVue3Body.js +++ /dev/null @@ -1,67 +0,0 @@ -const buildVue3Body = ({ id, html, js, css, version, hyperformulaVersion, preset }) => { - const addVuexDependencies = preset.includes('vuex') - ? ` - "vuex": "^4.0.2",` - : ''; - - return { - files: { - 'package.json': { - content: `{ - "name": "handsontable", - "version": "1.0.0", - "description": "", - "main": "src/main.js", - "scripts": { - "start": "vue-cli-service serve", - "build": "vue-cli-service build" - }, - "dependencies": { - "vue": "3.2.45",${addVuexDependencies} - "hyperformula": "${hyperformulaVersion}", - "handsontable": "${version}", - "@handsontable/vue3": "${version}" - }, - "devDependencies": { - "@vue/cli-service": "5.0.8" - } -}` - }, - 'vue.config.js': { - content: `module.exports = { - runtimeCompiler: true -}` - }, - 'public/index.html': { - content: ` - - - - - Handsontable - - - - ${html || `
`} - -` - }, - 'src/styles.css': { - content: css - }, - 'src/main.js': { - content: `import { createApp } from "vue"; -import "./styles.css"; -import ExampleComponent from "./ExampleComponent.js"; - -createApp(ExampleComponent).mount("#${id}"); -` - }, - 'src/ExampleComponent.js': { - content: js - } - } - }; -}; - -module.exports = { buildVue3Body }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/buildVueBody.js b/docs/.vuepress/plugins/examples/code-structure-builder/buildVueBody.js deleted file mode 100644 index 3d20cdf68c..0000000000 --- a/docs/.vuepress/plugins/examples/code-structure-builder/buildVueBody.js +++ /dev/null @@ -1,76 +0,0 @@ -const buildVueBody = ({ id, html, js, css, version, hyperformulaVersion, preset }) => { - const addVuexDependencies = preset.includes('vuex') - ? ` - "vuex": "^3.6.2",` - : ''; - const addAdvancedDependencies = preset.includes('advanced') - ? ` - "vuex": "^3.6.2", - "vue-color": "2.8.1", - "vue-star-rating": "1.7.0",` - : ''; - - return { - files: { - 'package.json': { - content: `{ - "name": "handsontable", - "version": "1.0.0", - "description": "", - "main": "src/main.js", - "scripts": { - "start": "vue-cli-service serve", - "build": "vue-cli-service build" - }, - "dependencies": { - "vue": "2.7.14",${addVuexDependencies}${addAdvancedDependencies} - "hyperformula": "${hyperformulaVersion}", - "handsontable": "${version}", - "@handsontable/vue": "${version}" - }, - "devDependencies": { - "@vue/cli-service": "5.0.8" - } -}` - }, - 'vue.config.js': { - content: `module.exports = { - runtimeCompiler: true -}` - }, - 'public/index.html': { - content: ` - - - - - Handsontable - - - - ${html || `
`} - -` - }, - 'src/styles.css': { - content: css - }, - 'src/main.js': { - content: `import Vue from "vue"; -import "./styles.css"; -import ExampleComponent from "./ExampleComponent.js"; - -new Vue({ - ...ExampleComponent, - el: '#${id}', -}); -` - }, - 'src/ExampleComponent.js': { - content: js - }, - } - }; -}; - -module.exports = { buildVueBody }; diff --git a/docs/.vuepress/plugins/examples/code-structure-builder/getBody.js b/docs/.vuepress/plugins/examples/code-structure-builder/getBody.js deleted file mode 100644 index d125067911..0000000000 --- a/docs/.vuepress/plugins/examples/code-structure-builder/getBody.js +++ /dev/null @@ -1,42 +0,0 @@ -const { buildAngularBody } = require('./buildAngularBody'); -const { buildJavascriptBody } = require('./buildJavascriptBody'); -const { buildReactBody } = require('./buildReactBody'); -const { buildVue3Body } = require('./buildVue3Body'); -const { buildVueBody } = require('./buildVueBody'); - -const getBody = ({ id, html, js, css, version, preset, sandbox, lang }) => { - const hyperformulaVersion = '^2.4.0'; - - if (/hot(-.*)?/.test(preset)) { - return buildJavascriptBody({ - id, - html, - js, - css, - version, - hyperformulaVersion, - sandbox, - lang: lang === 'JavaScript' ? 'js' : 'ts' - }); - } else if (/react(-.*)?/.test(preset)) { - return buildReactBody({ - js, - css, - version, - hyperformulaVersion, - preset, - sandbox, - lang: lang === 'JavaScript' ? 'jsx' : 'tsx' - }); - } else if (/vue3(-.*)?/.test(preset)) { - return buildVue3Body({ id, html, js, css, version, hyperformulaVersion, preset }); - } else if (/vue(-.*)?/.test(preset)) { - return buildVueBody({ id, html, js, css, version, hyperformulaVersion, preset }); - } else if (/angular(-.*)?/.test(preset)) { - return buildAngularBody({ html, js, version, hyperformulaVersion }); - } - - return undefined; -}; - -module.exports = { getBody }; diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js index 76d1867163..2bdeb17728 100644 --- a/docs/.vuepress/plugins/examples/examples.js +++ b/docs/.vuepress/plugins/examples/examples.js @@ -1,13 +1,13 @@ +const Token = require('markdown-it/lib/token'); +const { buildCode } = require('./code-builder'); +const { stackblitz } = require('./stackblitz'); + /** * Matches into: `example #ID .class :preset --css 2 --html 0 --js 1 --ts 3 --no-edit`. * * @type {RegExp} */ const EXAMPLE_REGEX = /^(example)\s*(#\S*|)\s*(\.\S*|)\s*(:\S*|)\s*([\S|\s]*)$/; -const Token = require('markdown-it/lib/token'); -const { buildCode } = require('./code-builder'); -const { addCodeForPreset } = require('./add-code-for-preset'); -const { stackblitz } = require('./stackblitz'); const parseCode = (content) => { if (!content) return ''; @@ -16,7 +16,6 @@ const parseCode = (content) => { // Remove the all "/* start:skip-in-preview */" and "/* end:skip-in-preview */" comments .replace(/\/\*(\s+)?(start|end):skip-in-preview(\s+)?\*\/\n/gm, '') // Remove the code between "/* start:skip-in-compilation */" and "/* end:skip-in-compilation */" expressions - // eslint-disable-next-line max-len .replace(/\/\*(\s+)?start:skip-in-compilation(\s+)?\*\/\n.*?\/\*(\s+)?end:skip-in-compilation(\s+)?\*\/\n/msg, '') // Remove /* end-file */ .replace(/\/\* end-file \*\//gm, ''); @@ -32,7 +31,7 @@ const parseCodeSandbox = (content) => { .replace(/\/\*(\s+)?(start|end):skip-in-compilation(\s+)?\*\/\n/gm, ''); }; -module.exports = function(docsVersion, base) { +module.exports = function() { return { type: 'example', render(tokens, index, _opts, env) { @@ -72,10 +71,8 @@ module.exports = function(docsVersion, base) { const tsToken = tsPos ? tokens[tsIndex] : undefined; // Parse code - const jsTokenWithBasePath = jsToken?.content?.replaceAll('{{$basePath}}', base); - const tsTokenWithBasePath = tsToken?.content?.replaceAll('{{$basePath}}', base); - const codeToCompile = parseCode(jsTokenWithBasePath); - const tsCodeToCompileSandbox = parseCodeSandbox(tsTokenWithBasePath); + const codeToCompile = parseCode(jsToken?.content); + const tsCodeToCompileSandbox = parseCodeSandbox(tsToken?.content); [htmlIndex, jsIndex, tsIndex, cssIndex].filter(x => !!x).sort().reverse().forEach((x) => { tokens.splice(x, 1); @@ -90,13 +87,12 @@ module.exports = function(docsVersion, base) { tokens.splice(index + 1, 0, ...newTokens); - const codeForPreset = addCodeForPreset(codeToCompile, preset, id); - const code = buildCode( - id + (preset.includes('angular') ? '.ts' : '.jsx'), - codeForPreset, + const builtCode = buildCode( + id + '.js', + codeToCompile, env.relativePath ); - const encodedCode = encodeURI(code); + const encodedCode = encodeURI(builtCode); return `
@@ -110,15 +106,10 @@ module.exports = function(docsVersion, base) { htmlContent, tsCodeToCompileSandbox, cssContent, - docsVersion, - preset, - 'TypeScript' + 'ts' )}
`; }, }; }; - -// - remove non-needed glue-code -// - all demos need to be reworked to the 3-file format diff --git a/docs/.vuepress/plugins/examples/stackblitz.js b/docs/.vuepress/plugins/examples/stackblitz.js index 28f4942934..6a4042cc6e 100644 --- a/docs/.vuepress/plugins/examples/stackblitz.js +++ b/docs/.vuepress/plugins/examples/stackblitz.js @@ -1,28 +1,14 @@ -const { getBody } = require('./code-structure-builder/getBody'); +const { buildJavascriptBody } = require('./buildJavascriptBody'); -const stackblitz = (id, html, js, css, docsVersion, preset, lang) => { - const body = getBody({ id, html, js, css, docsVersion, preset, sandbox: 'stackblitz', lang }); +const stackblitz = (id, html, js, css, lang) => { + const hyperformulaVersion = 'latest'; + const body = buildJavascriptBody({ id, html, js, css, hyperformulaVersion, lang }); const projects = body?.files ? Object.entries(body?.files).map(([key, value]) => ( `` )) : []; - const addReactDependencies = preset.includes('react') - // eslint-disable-next-line max-len - ? ', "@handsontable/react": "latest", "react": "latest", "react-dom": "latest", "redux": "latest", "react-redux": "latest", "react-colorful": "latest", "react-star-rating-component": "latest", "@types/react": "latest", "@types/react-dom": "latest"' - : ''; - - const getTemplate = () => { - if (preset.includes('react')) return 'create-react-app'; - - if (preset.includes('hot') && lang === 'JavaScript') return 'javascript'; - - if (preset.includes('hot') && lang === 'TypeScript') return 'typescript'; - - return 'node'; - }; - return `
{ target="_blank" > ${projects.join('\n')} - - + - + From dc6c826b10407a1342aacd8f6053343ffcd4a73e Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Fri, 27 Sep 2024 13:30:13 +0200 Subject: [PATCH 13/41] Remove not needed vuepress plugins --- docs/.vuepress/config.js | 4 - .../plugins/examples/buildJavascriptBody.js | 39 ------ docs/.vuepress/plugins/examples/stackblitz.js | 38 +++++- .../index.js | 115 ------------------ .../onlyForContainerHelpers.js | 88 -------------- .../markdown-it-header-injection/index.js | 43 ------- 6 files changed, 37 insertions(+), 290 deletions(-) delete mode 100644 docs/.vuepress/plugins/examples/buildJavascriptBody.js delete mode 100644 docs/.vuepress/plugins/markdown-it-conditional-container/index.js delete mode 100644 docs/.vuepress/plugins/markdown-it-conditional-container/onlyForContainerHelpers.js delete mode 100644 docs/.vuepress/plugins/markdown-it-header-injection/index.js diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index e59df03114..de3b2460e0 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -4,8 +4,6 @@ const footnotePlugin = require('markdown-it-footnote'); const searchBoxPlugin = require('./plugins/search-box'); const examples = require('./plugins/examples/examples'); const HyperFormula = require('../../dist/hyperformula.full'); -const firstHeaderInjection = require('./plugins/markdown-it-header-injection'); -const conditionalContainer = require('./plugins/markdown-it-conditional-container'); const includeCodeSnippet = require('./plugins/markdown-it-include-code-snippet'); const searchPattern = new RegExp('^/api', 'i'); @@ -107,8 +105,6 @@ module.exports = { }) md.use(footnotePlugin) md.use(includeCodeSnippet) - md.use(conditionalContainer) - md.use(firstHeaderInjection) } }, // TODO: It doesn't work. It's seems that this option is bugged. Documentation says that this option is configurable, diff --git a/docs/.vuepress/plugins/examples/buildJavascriptBody.js b/docs/.vuepress/plugins/examples/buildJavascriptBody.js deleted file mode 100644 index 3a79ebb4e8..0000000000 --- a/docs/.vuepress/plugins/examples/buildJavascriptBody.js +++ /dev/null @@ -1,39 +0,0 @@ -const buildJavascriptBody = ({ id, html, js, css, hyperformulaVersion, lang }) => { - return { - files: { - 'package.json': { - content: `{ - "name": "hyperformula-demo", - "version": "1.0.0", - "description": "", - "dependencies": { - "hyperformula": "${hyperformulaVersion}" - } -}` - }, - 'index.html': { - content: ` - - - - - HyperFormula demo - - - - ${html || `
`} - -` - }, - 'styles.css': { - content: css - }, - [`index.${lang}`]: { - content: `import './styles.css' -${js}` - }, - } - }; -}; - -module.exports = { buildJavascriptBody }; diff --git a/docs/.vuepress/plugins/examples/stackblitz.js b/docs/.vuepress/plugins/examples/stackblitz.js index 6a4042cc6e..b60414d5da 100644 --- a/docs/.vuepress/plugins/examples/stackblitz.js +++ b/docs/.vuepress/plugins/examples/stackblitz.js @@ -1,4 +1,40 @@ -const { buildJavascriptBody } = require('./buildJavascriptBody'); +const buildJavascriptBody = ({ id, html, js, css, hyperformulaVersion, lang }) => { + return { + files: { + 'package.json': { + content: `{ + "name": "hyperformula-demo", + "version": "1.0.0", + "description": "", + "dependencies": { + "hyperformula": "${hyperformulaVersion}" + } +}` + }, + 'index.html': { + content: ` + + + + + HyperFormula demo + + + + ${html || `
`} + +` + }, + 'styles.css': { + content: css + }, + [`index.${lang}`]: { + content: `import './styles.css' +${js}` + }, + } + }; +}; const stackblitz = (id, html, js, css, lang) => { const hyperformulaVersion = 'latest'; diff --git a/docs/.vuepress/plugins/markdown-it-conditional-container/index.js b/docs/.vuepress/plugins/markdown-it-conditional-container/index.js deleted file mode 100644 index 23e07b2204..0000000000 --- a/docs/.vuepress/plugins/markdown-it-conditional-container/index.js +++ /dev/null @@ -1,115 +0,0 @@ -const chalk = require('chalk'); - -/* eslint-disable */ -/** - * Container used to display blocks of content only for to specific frameworks. - * - * Usage: - * ``` - * ::: only-for react - * Content to be displayed only for React documentation. - * ::: - * - * ::: only-for javascript react vue - * Content to be displayed only for JS, React and Vue documentation. - * ::: - * ``` - */ -module.exports = function conditionalContainer(markdown) { - const openAndCloseTagOneliner = /::: only-for (((react|javascript) ?)+)(.*?):::$/ms; // It is multi line text. - const openTokenContent = /(?:\n?)::: only-for (((react|javascript) ?)+)\n?/; - const fullMatchOpenToken = /^(?:\n?)::: only-for (((react|javascript) ?)+)\n?$/; - const closeTokenContent = /(?:\n?):::(?:\n?)$/; - const fullMatchCloseToken = /^(?:\n?):::(?:\n?)$/; - const markupForCustomContainer = ':::'; - const newLineTokenType = 'softbreak'; - const capturedGroupIndex = 1; - let endIndex; - - const removeValueAndNewLine = ({ token, regexp, env }) => { - // Removing value from token's content. - token.content = token.content.replace(regexp, ''); - - // Some tokens may not have children. Children are component parts of the displayed text in most cases. - if (token.children === null) { - return; - } - - let childrenIndex = token.children.findIndex(childrenToken => regexp.test(childrenToken.content)); - - // Some tokens contains children which also represents the removed value (and they are displayed in the output file). - if (childrenIndex !== -1) { - const nextElement = token.children[childrenIndex + 1]; - const previousElement = token.children[childrenIndex - 1]; - let howMany = 1; - - if (childrenIndex > 0 && previousElement.type === newLineTokenType) { - childrenIndex -= 1; - howMany += 1; - } - - if (nextElement?.type === newLineTokenType) { - howMany += 1; - } - - token.children.splice(childrenIndex, howMany); - } else { - // eslint-disable-next-line no-console - console.error(`${chalk.red('\nUnexpected error while processing a conditional container (::: only-for) in the file ' - `"${env.relativePath}".` + - ` Please check the file or the resulting page "${env.frontmatter.permalink}".` - )}`); - } - }; - - const cleanTokens = ({ tokens, token, tokenIndex, preciseRegexp, lessPreciseRegexp, env }) => { - if (preciseRegexp.test(token.content)) { - tokens.splice(tokenIndex, 1); - - } else { - removeValueAndNewLine({ token, regexp: lessPreciseRegexp, env }); - } - }; - - const findAndRemove = (state) => { - const relativePath = state.env?.relativePath; // Sometimes the `env` key is an empty object. - - if (relativePath === void 0) { - return; - } - - const env = state.env; - - for (let index = state.tokens.length - 1; index >= 0; index -= 1) { - const token = state.tokens[index]; - // We don't create custom container intentionally. It can create paragraphs or break listed elements. - const isNotNativeContainer = token.markup !== markupForCustomContainer; - - if (isNotNativeContainer) { - if (openAndCloseTagOneliner.test(token.content)) { - const onlyForFrameworks = openAndCloseTagOneliner.exec(token.content)[capturedGroupIndex].split(' '); - - removeValueAndNewLine({ token, regexp: openTokenContent, env }); - removeValueAndNewLine({ token, regexp: closeTokenContent, env }); - } else if (closeTokenContent.test(token.content)) { - - endIndex = index; - } else if (openTokenContent.test(token.content)) { - const onlyForFrameworks = openTokenContent.exec(token.content)[capturedGroupIndex].split(' '); - - if (endIndex === void 0) { - console.error(`${chalk.red('\nUnexpected error while processing a conditional container (::: only-for)' + - ` in the file "${getNormalizedPath(env.relativePath)}". It seems that the opening token (::: only-for)` + - ' exists, but the ending token (:::) does not.' - )}`); - } - - cleanTokens({ tokens: state.tokens, token: state.tokens[endIndex], tokenIndex: endIndex, lessPreciseRegexp: closeTokenContent, preciseRegexp: fullMatchCloseToken, env }); - cleanTokens({ tokens: state.tokens, token, tokenIndex: index, lessPreciseRegexp: openTokenContent, preciseRegexp: fullMatchOpenToken, env }); - } - } - } - }; - - markdown.core.ruler.push('conditional_container', findAndRemove); -}; diff --git a/docs/.vuepress/plugins/markdown-it-conditional-container/onlyForContainerHelpers.js b/docs/.vuepress/plugins/markdown-it-conditional-container/onlyForContainerHelpers.js deleted file mode 100644 index a715eb7710..0000000000 --- a/docs/.vuepress/plugins/markdown-it-conditional-container/onlyForContainerHelpers.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * A factory for creating function for `markdown-it-anchor` plugin's `permalinkSymbol` configuration option. - * - * @param {Set} uniqueSlugs An unique set, where are stored slugs. - * @returns {Function} - */ -function getPermalinkHrefMethod(uniqueSlugs) { - return function(slug, state) { - const slugify = state.md.slugify; - const openTokenContent = /(?:\n?)::: only-for (((react|javascript) ?)+)\n?/; - const closeTokenContent = /(?:\n?):::(?:\n?)$/; - const markupForCustomContainer = ':::'; - const headerOpenType = 'heading_open'; - const headerCloseType = 'heading_close'; - let endIndex; - - if (/(.*)-(\d)+$/.test(slug) === false) { - return `#${slug}`; - } - - const handleTokensInsideOnlyForContainer = (action) => { - for (let index = state.tokens.length - 1; index >= 0; index -= 1) { - const token = state.tokens[index]; - // We don't create custom container intentionally inside `markdown-it-conditional-container` plugin. - const isNotNativeContainer = token.markup !== markupForCustomContainer; - - if (isNotNativeContainer) { - if (closeTokenContent.test(token.content)) { - - endIndex = index; - } else if (openTokenContent.test(token.content)) { - action(state.tokens.slice(index, endIndex)); - } - } - } - }; - - const getTokensInsideHeaders = (tokens) => { - return tokens.filter((_, tokenIndex) => { - if (tokenIndex === 0 || tokenIndex === tokens.length - 1) { - return false; - - } else if (tokens[tokenIndex - 1]?.type === headerOpenType && - tokens[tokenIndex + 1]?.type === headerCloseType) { - // Tokens being children of some header. - return true; - } - - return false; - }); - }; - - const getParsedSlugsFromHeaders = (tokens) => { - return getTokensInsideHeaders(tokens).map(headerContentTag => slugify(headerContentTag.content)); - }; - - const parseAndChangeDuplicatedSlug = (tokensInside) => { - getParsedSlugsFromHeaders(tokensInside).some((headerSlug) => { // Array.some for purpose of stopping the loop. - const headerSlugWithNumber = new RegExp(`${headerSlug}-(\\d)+$`); - - if (headerSlugWithNumber.test(slug)) { - // Remove the `-[number]` suffix from the permalink href attribute. - const duplicatedSlugsMatch = headerSlugWithNumber.exec(slug); - - if (duplicatedSlugsMatch) { - // Updating a set of slugs, which will be used by another method. - uniqueSlugs.add(headerSlug); - - // Removed the `-[number]` suffix. - slug = `${headerSlug}`; - - return true; // Breaks the loop. - } - } - - return false; // Continue looping. - }); - }; - - handleTokensInsideOnlyForContainer(parseAndChangeDuplicatedSlug); - - return `#${slug}`; - }; -} - -module.exports = { - getPermalinkHrefMethod, -}; diff --git a/docs/.vuepress/plugins/markdown-it-header-injection/index.js b/docs/.vuepress/plugins/markdown-it-header-injection/index.js deleted file mode 100644 index 887e97ada2..0000000000 --- a/docs/.vuepress/plugins/markdown-it-header-injection/index.js +++ /dev/null @@ -1,43 +0,0 @@ -module.exports = function firstHeaderInjection(markdown) { - const insertedTokenTag = 'span'; - const insertedOpenTokenType = 'paragraph_open'; - const insertedCloseTokenType = 'paragraph_close'; - const foundTokenTag = 'h1'; - const foundOpenTokenType = 'heading_open'; - - const findAndInject = (state) => { - const Token = state.Token; - const relativePath = state.env?.relativePath; // Sometimes the `env` key is an empty object. - - if (relativePath === void 0) { - return; - } - - let insertSpan = false; - - // Find the first header and insert some element to it. - state.tokens.every((token) => { - // Next token represents a place where new HTML tag can be injected. - if (insertSpan && token.type === 'inline') { - const spanOpen = new Token(insertedOpenTokenType, insertedTokenTag, 1); - const spanClose = new Token(insertedCloseTokenType, insertedTokenTag, -1); - const text = new Token('html_block', '', 0); - - text.content = `Data Grid`; - - spanOpen.attrSet('class', 'header-framework'); - token.children.unshift(spanOpen, text, spanClose); // Add HTML element right after first `h1` tag on the site. - - return false; // Stops the iteration. - } - - if (token.type === foundOpenTokenType && token.tag === foundTokenTag) { - insertSpan = true; - } - - return true; - }); - }; - - markdown.core.ruler.push('first_header_injection', findAndInject); -}; From 01b7d7ad7d020ecdb68cfc8b5bef7060a531cd8d Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Fri, 27 Sep 2024 13:39:51 +0200 Subject: [PATCH 14/41] Fix linter error --- docs/examples/demo/example1.html | 2 +- docs/examples/demo/example1.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/demo/example1.html b/docs/examples/demo/example1.html index e318f98704..976656b64e 100644 --- a/docs/examples/demo/example1.html +++ b/docs/examples/demo/example1.html @@ -24,4 +24,4 @@
-
\ No newline at end of file +
diff --git a/docs/examples/demo/example1.ts b/docs/examples/demo/example1.ts index fabfae2442..1caf36002b 100644 --- a/docs/examples/demo/example1.ts +++ b/docs/examples/demo/example1.ts @@ -56,7 +56,7 @@ function bindEvents() { }); resetButton.addEventListener("click", () => { - resetTable(tableData); + resetTable(); }); } From 2de2bcbf6cf7144e659e5c8ff6c064d3bc52feff Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Tue, 1 Oct 2024 12:04:26 +0200 Subject: [PATCH 15/41] Reformat demo/example1.ts file --- docs/examples/demo/example1.ts | 56 ++++++++-------------------------- 1 file changed, 13 insertions(+), 43 deletions(-) diff --git a/docs/examples/demo/example1.ts b/docs/examples/demo/example1.ts index 1caf36002b..f306f12ec0 100644 --- a/docs/examples/demo/example1.ts +++ b/docs/examples/demo/example1.ts @@ -4,21 +4,12 @@ import HyperFormula from 'hyperformula'; console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); -/** - * Initial table data. - */ const tableData = [ ["Greg Black", 4.66, "=B1*1.3", "=AVERAGE(B1:C1)", "=SUM(B1:C1)"], ["Anne Carpenter", 5.25, "=$B$2*30%", "=AVERAGE(B2:C2)", "=SUM(B2:C2)"], ["Natalie Dem", 3.59, "=B3*2.7+2+1", "=AVERAGE(B3:C3)", "=SUM(B3:C3)"], ["John Sieg", 12.51, "=B4*(1.22+1)", "=AVERAGE(B4:C4)", "=SUM(B4:C4)"], - [ - "Chris Aklips", - 7.63, - "=B5*1.1*SUM(10,20)+1", - "=AVERAGE(B5:C5)", - "=SUM(B5:C5)" - ] + ["Chris Aklips", 7.63, "=B5*1.1*SUM(10,20)+1", "=AVERAGE(B5:C5)", "=SUM(B5:C5)"] ]; // Create an empty HyperFormula instance. @@ -31,28 +22,21 @@ const sheetName = hf.addSheet("main"); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. -hf.setCellContents( - { - row: 0, - col: 0, - sheet: sheetId - }, - tableData -); +hf.setCellContents({ + row: 0, col: 0, sheet: sheetId +}, tableData); // Add named expressions for the "TOTAL" row. hf.addNamedExpression("Year_1", "=SUM(main!$B$1:main!$B$5)"); hf.addNamedExpression("Year_2", "=SUM(main!$C$1:main!$C$5)"); -/** - * Bind the events to the buttons. - */ +// Bind the events to the buttons. function bindEvents() { const runButton = document.querySelector("#run"); const resetButton = document.querySelector("#reset"); runButton.addEventListener("click", () => { - runCalculations(hf, sheetId); + runCalculations(); }); resetButton.addEventListener("click", () => { @@ -71,13 +55,13 @@ function renderTable(calculated = false) { const tbodyDOM = document.querySelector(".example tbody"); const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; const totals = ["=SUM(Year_1)", "=SUM(Year_2)"]; - const { height, width } = hf.getSheetDimensions(sheetId); + const {height, width} = hf.getSheetDimensions(sheetId); let newTbodyHTML = ""; let totalRowsHTML = ""; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { - const cellAddress = { sheet: sheetId, col, row }; + const cellAddress = {sheet: sheetId, col, row}; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = calculated || !cellHasFormula; let cellValue = ""; @@ -92,9 +76,7 @@ function renderTable(calculated = false) { cellValue = hf.getCellFormula(cellAddress); } - newTbodyHTML += ` + newTbodyHTML += ` ${cellValue} `; } @@ -105,18 +87,10 @@ function renderTable(calculated = false) { totalRowsHTML = ` TOTAL - ${ - calculated - ? hf.calculateFormula(totals[0], sheetId).toFixed(2) - : totals[0] - } + ${calculated ? hf.calculateFormula(totals[0], sheetId).toFixed(2) : totals[0]} - ${ - calculated - ? hf.calculateFormula(totals[1], sheetId).toFixed(2) - : totals[1] - } + ${calculated ? hf.calculateFormula(totals[1], sheetId).toFixed(2) : totals[1]} `; @@ -126,16 +100,12 @@ function renderTable(calculated = false) { tbodyDOM.innerHTML = newTbodyHTML; } -/** - * Replace formulas with their results. - */ +// Replace formulas with their results. function runCalculations() { renderTable(true); } -/** - * Replace the values in the table with initial data. - */ +// Replace the values in the table with initial data. function resetTable() { renderTable(); } From 5ba4b3d6c381018d967889ab400ac9ba11fa0489 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Tue, 1 Oct 2024 15:17:36 +0200 Subject: [PATCH 16/41] Add advanced-usage demo --- docs/.vuepress/plugins/examples/stackblitz.js | 7 +- docs/examples/advanced-usage/example1.css | 90 +++++++++++++ docs/examples/advanced-usage/example1.html | 53 ++++++++ docs/examples/advanced-usage/example1.js | 126 ++++++++++++++++++ docs/examples/advanced-usage/example1.ts | 124 +++++++++++++++++ docs/examples/demo/example1.js | 19 +-- docs/guide/advanced-usage.md | 15 ++- 7 files changed, 413 insertions(+), 21 deletions(-) create mode 100644 docs/examples/advanced-usage/example1.css create mode 100644 docs/examples/advanced-usage/example1.html create mode 100644 docs/examples/advanced-usage/example1.js create mode 100644 docs/examples/advanced-usage/example1.ts diff --git a/docs/.vuepress/plugins/examples/stackblitz.js b/docs/.vuepress/plugins/examples/stackblitz.js index b60414d5da..c9a004af06 100644 --- a/docs/.vuepress/plugins/examples/stackblitz.js +++ b/docs/.vuepress/plugins/examples/stackblitz.js @@ -5,7 +5,7 @@ const buildJavascriptBody = ({ id, html, js, css, hyperformulaVersion, lang }) = content: `{ "name": "hyperformula-demo", "version": "1.0.0", - "description": "", + "main": "index.html", "dependencies": { "hyperformula": "${hyperformulaVersion}" } @@ -39,6 +39,7 @@ ${js}` const stackblitz = (id, html, js, css, lang) => { const hyperformulaVersion = 'latest'; const body = buildJavascriptBody({ id, html, js, css, hyperformulaVersion, lang }); + const template = lang === 'ts' ? 'typescript' : 'node'; const projects = body?.files ? Object.entries(body?.files).map(([key, value]) => ( @@ -55,9 +56,9 @@ const stackblitz = (id, html, js, css, lang) => { ${projects.join('\n')} - + \ No newline at end of file diff --git a/docs/examples/advanced-usage/example1.js b/docs/examples/advanced-usage/example1.js new file mode 100644 index 0000000000..952e3e6c61 --- /dev/null +++ b/docs/examples/advanced-usage/example1.js @@ -0,0 +1,126 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; + +/* end:skip-in-compilation */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +// first column represents players' IDs +// second column represents players' scores +const playersAData = [ + ['1', '2'], + ['2', '3'], + ['3', '5'], + ['4', '7'], + ['5', '13'], + ['6', '17'], +]; + +const playersBData = [ + ['7', '19'], + ['8', '31'], + ['9', '61'], + ['10', '89'], + ['11', '107'], + ['12', '127'], +]; + +// in a cell A1 a formula checks which team is a winning one +// in cells A2 and A3 formulas calculate the average score of players +const formulasData = [ + ['=IF(Formulas!A2>Formulas!A3,"TeamA","TeamB")'], + ['=AVERAGE(TeamA!B1:B6)'], + ['=AVERAGE(TeamB!B1:B6)'], +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: 'gpl-v3', +}); + +const sheetInfo = { + teamA: { sheetName: 'TeamA' }, + teamB: { sheetName: 'TeamB' }, + formulas: { sheetName: 'Formulas' }, +}; + +// add 'TeamA' sheet +hf.addSheet(sheetInfo.teamA.sheetName); +// insert playersA content into targeted 'TeamA' sheet +hf.setSheetContent(hf.getSheetId(sheetInfo.teamA.sheetName), playersAData); +// add 'TeamB' sheet +hf.addSheet(sheetInfo.teamB.sheetName); +// insert playersB content into targeted 'TeamB' sheet +hf.setSheetContent(hf.getSheetId(sheetInfo.teamB.sheetName), playersBData); +// add a sheet named 'Formulas' +hf.addSheet(sheetInfo.formulas.sheetName); +// add formulas to that sheet +hf.setSheetContent(hf.getSheetId(sheetInfo.formulas.sheetName), formulasData); + +/** + * Fill the HTML table with data. + * + * @param {string} sheetName Sheet name. + */ +function renderTable(sheetName) { + const sheetId = hf.getSheetId(sheetName); + const tbodyDOM = document.querySelector(`#${sheetName}-container tbody`); + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + let cellValue = ''; + + if (!hf.isCellEmpty(cellAddress) && !cellHasFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += `${cellValue}`; + } + + newTbodyHTML += ''; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Render the result block. + */ +function renderResult() { + const resultOutputDOM = document.querySelector('#result .output'); + const cellAddress = hf.simpleCellAddressFromString( + `${sheetInfo.formulas.sheetName}!A1`, + hf.getSheetId(sheetInfo.formulas.sheetName) + ); + + resultOutputDOM.innerHTML = ` + ${hf.getCellValue(cellAddress)} won! + `; +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector('#run'); + + runButton.addEventListener('click', () => { + renderResult(); + }); +} + +// Bind the button events. +bindEvents(); + +// Render the preview tables. +for (const [tableName, tableInfo] of Object.entries(sheetInfo)) { + renderTable(tableInfo.sheetName); +} diff --git a/docs/examples/advanced-usage/example1.ts b/docs/examples/advanced-usage/example1.ts new file mode 100644 index 0000000000..e4849ce3bc --- /dev/null +++ b/docs/examples/advanced-usage/example1.ts @@ -0,0 +1,124 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +/* end:skip-in-compilation */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +// first column represents players' IDs +// second column represents players' scores +const playersAData = [ + ["1", "2"], + ["2", "3"], + ["3", "5"], + ["4", "7"], + ["5", "13"], + ["6", "17"] +]; +const playersBData = [ + ["7", "19"], + ["8", "31"], + ["9", "61"], + ["10", "89"], + ["11", "107"], + ["12", "127"] +]; + +// in a cell A1 a formula checks which team is a winning one +// in cells A2 and A3 formulas calculate the average score of players +const formulasData = [ + ['=IF(Formulas!A2>Formulas!A3,"TeamA","TeamB")'], + ["=AVERAGE(TeamA!B1:B6)"], + ["=AVERAGE(TeamB!B1:B6)"] +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: "gpl-v3" +}); + +const sheetInfo = { + teamA: { sheetName: "TeamA" }, + teamB: { sheetName: "TeamB" }, + formulas: { sheetName: "Formulas" }, +}; + +// add 'TeamA' sheet +hf.addSheet(sheetInfo.teamA.sheetName); +// insert playersA content into targeted 'TeamA' sheet +hf.setSheetContent(hf.getSheetId(sheetInfo.teamA.sheetName), playersAData); + +// add 'TeamB' sheet +hf.addSheet(sheetInfo.teamB.sheetName); +// insert playersB content into targeted 'TeamB' sheet +hf.setSheetContent(hf.getSheetId(sheetInfo.teamB.sheetName), playersBData); + +// add a sheet named 'Formulas' +hf.addSheet(sheetInfo.formulas.sheetName); +// add formulas to that sheet +hf.setSheetContent(hf.getSheetId(sheetInfo.formulas.sheetName), formulasData); + + +/** + * Fill the HTML table with data. + * + * @param {string} sheetName Sheet name. + */ +function renderTable(sheetName) { + const sheetId = hf.getSheetId(sheetName); + const tbodyDOM = document.querySelector(`#${sheetName}-container tbody`); + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + let cellValue = ""; + + if (!hf.isCellEmpty(cellAddress) && !cellHasFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += `${cellValue}`; + } + + newTbodyHTML += ""; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Render the result block. + */ +function renderResult() { + const resultOutputDOM = document.querySelector("#result .output"); + const cellAddress = hf.simpleCellAddressFromString( + `${sheetInfo.formulas.sheetName}!A1`, hf.getSheetId(sheetInfo.formulas.sheetName) + ); + + resultOutputDOM.innerHTML = ` + ${hf.getCellValue(cellAddress)} won! + `; +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector("#run"); + + runButton.addEventListener("click", () => { + renderResult(); + }); +} + +// Bind the button events. +bindEvents(); + +// Render the preview tables. +for (const [tableName, tableInfo] of Object.entries(sheetInfo)) { + renderTable(tableInfo.sheetName); +} diff --git a/docs/examples/demo/example1.js b/docs/examples/demo/example1.js index 63fd56326d..25840b2305 100644 --- a/docs/examples/demo/example1.js +++ b/docs/examples/demo/example1.js @@ -7,9 +7,6 @@ console.log( 'color: blue; font-weight: bold' ); -/** - * Initial table data. - */ const tableData = [ ['Greg Black', 4.66, '=B1*1.3', '=AVERAGE(B1:C1)', '=SUM(B1:C1)'], ['Anne Carpenter', 5.25, '=$B$2*30%', '=AVERAGE(B2:C2)', '=SUM(B2:C2)'], @@ -46,18 +43,16 @@ hf.setCellContents( hf.addNamedExpression('Year_1', '=SUM(main!$B$1:main!$B$5)'); hf.addNamedExpression('Year_2', '=SUM(main!$C$1:main!$C$5)'); -/** - * Bind the events to the buttons. - */ +// Bind the events to the buttons. function bindEvents() { const runButton = document.querySelector('#run'); const resetButton = document.querySelector('#reset'); runButton.addEventListener('click', () => { - runCalculations(hf, sheetId); + runCalculations(); }); resetButton.addEventListener('click', () => { - resetTable(tableData); + resetTable(); }); } @@ -121,16 +116,12 @@ function renderTable(calculated = false) { tbodyDOM.innerHTML = newTbodyHTML; } -/** - * Replace formulas with their results. - */ +// Replace formulas with their results. function runCalculations() { renderTable(true); } -/** - * Replace the values in the table with initial data. - */ +// Replace the values in the table with initial data. function resetTable() { renderTable(); } diff --git a/docs/guide/advanced-usage.md b/docs/guide/advanced-usage.md index 4a8300f386..7ccb1f64c1 100644 --- a/docs/guide/advanced-usage.md +++ b/docs/guide/advanced-usage.md @@ -121,7 +121,14 @@ console.log(winningTeam) ## Demo - +::: example #example1 --html 1 --css 2 --js 3 --ts 4 + +@[code](@/docs/examples/advanced-usage/example1.html) + +@[code](@/docs/examples/advanced-usage/example1.css) + +@[code](@/docs/examples/advanced-usage/example1.js) + +@[code](@/docs/examples/advanced-usage/example1.ts) + +::: From ca0b39d92ceab1fb5a350f6e153fa094889874d0 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Wed, 2 Oct 2024 13:08:04 +0200 Subject: [PATCH 17/41] Change the framework demos in the docs to use Codesandbox iframe instead of Stackblitz --- docs/guide/integration-with-angular.md | 7 +++++-- docs/guide/integration-with-react.md | 7 +++++-- docs/guide/integration-with-svelte.md | 7 +++++-- docs/guide/integration-with-vue.md | 9 ++++++--- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/docs/guide/integration-with-angular.md b/docs/guide/integration-with-angular.md index 0eb483004b..49dfdd17a2 100644 --- a/docs/guide/integration-with-angular.md +++ b/docs/guide/integration-with-angular.md @@ -7,6 +7,9 @@ For more details, see the [client-side installation](client-side-installation.md ## Demo diff --git a/docs/guide/integration-with-react.md b/docs/guide/integration-with-react.md index d58de06e04..418dc190a4 100644 --- a/docs/guide/integration-with-react.md +++ b/docs/guide/integration-with-react.md @@ -7,6 +7,9 @@ For more details, see the [client-side installation](client-side-installation.md ## Demo diff --git a/docs/guide/integration-with-svelte.md b/docs/guide/integration-with-svelte.md index c2488e6bfb..df9b9f5b86 100644 --- a/docs/guide/integration-with-svelte.md +++ b/docs/guide/integration-with-svelte.md @@ -7,6 +7,9 @@ For more details, see the [client-side installation](client-side-installation.md ## Demo diff --git a/docs/guide/integration-with-vue.md b/docs/guide/integration-with-vue.md index 62d4f36d8a..baf9b8bda0 100644 --- a/docs/guide/integration-with-vue.md +++ b/docs/guide/integration-with-vue.md @@ -11,6 +11,9 @@ This demo uses the [Vue 3](https://v3.vuejs.org/) framework. If you are looking ::: \ No newline at end of file + :src="`https://codesandbox.io/embed/github/handsontable/hyperformula-demos/tree/2.7.x/vue-3-demo?autoresize=1&fontsize=11&hidenavigation=1&theme=light&view=preview&v=${$page.buildDateURIEncoded}`" + style="width:100%; height:1070px; border:0; border-radius: 4px; overflow:hidden;" + title="handsontable/hyperformula-demos: react-demo" + allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" + sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"> + From 7b439ccd893be5ea115ffaee87ff5fe915af5bc6 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 3 Oct 2024 12:20:31 +0200 Subject: [PATCH 18/41] Add basic-operations demo --- docs/examples/basic-operations/example1.css | 171 +++++++ docs/examples/basic-operations/example1.html | 48 ++ docs/examples/basic-operations/example1.js | 461 ++++++++++++++++++ docs/examples/basic-operations/example1.ts | 464 +++++++++++++++++++ docs/guide/basic-operations.md | 18 +- 5 files changed, 1156 insertions(+), 6 deletions(-) create mode 100644 docs/examples/basic-operations/example1.css create mode 100644 docs/examples/basic-operations/example1.html create mode 100644 docs/examples/basic-operations/example1.js create mode 100644 docs/examples/basic-operations/example1.ts diff --git a/docs/examples/basic-operations/example1.css b/docs/examples/basic-operations/example1.css new file mode 100644 index 0000000000..485d3648f1 --- /dev/null +++ b/docs/examples/basic-operations/example1.css @@ -0,0 +1,171 @@ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +.example table { + table-layout: fixed; +} + +.example table tbody tr td, +.example table tbody tr th { + overflow: hidden; + text-overflow: ellipsis; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; + font-weight: bold; +} + +.example table tbody tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table thead tr th { + counter-increment: col-counter; +} + +.example table thead tr th::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; +} + +.example .crud-entry { + margin-bottom: 10px; +} + +.example #inputs input:focus, +.example #inputs select:focus, +.example #toolbar select:focus { + border-color: #1c49e4; +} + +.example input.inline, +.example select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example input::placeholder { + opacity: 0.55; +} + +.example button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #error-message { + display: none; +} + +.example #disclaimer { + font-size: 1rem; + opacity: 0.6; + margin: 0; +} + +.example input:disabled { + background-color: #f7f7f7; +} + +.example #sheet-select { + width: 12rem; +} + +.example #action-select { + width: 14rem; +} + +.example #preview-header { + margin: 30px 0 0 0; +} + +.example #inputs { + display: none; +} + +.example #inputs.error input { + border: 1px solid red; +} + +.example #error-message { + color: red; +} + +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/docs/examples/basic-operations/example1.html b/docs/examples/basic-operations/example1.html new file mode 100644 index 0000000000..30f3757829 --- /dev/null +++ b/docs/examples/basic-operations/example1.html @@ -0,0 +1,48 @@ +
+
+
+
+ +
+
+
+ +
+
+ + + +

+

+
+
+
+
+ + + + + + + + + + + +
+
+
diff --git a/docs/examples/basic-operations/example1.js b/docs/examples/basic-operations/example1.js new file mode 100644 index 0000000000..9485c587ff --- /dev/null +++ b/docs/examples/basic-operations/example1.js @@ -0,0 +1,461 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; + +/* end:skip-in-compilation */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +const ANIMATION_ENABLED = true; + +/** + * Return sample data for the provided number of rows and columns. + * + * @param {number} rows Amount of rows to create. + * @param {number} columns Amount of columns to create. + * @returns {string[][]} + */ +function getSampleData(rows, columns) { + const data = []; + + for (let r = 0; r < rows; r++) { + data.push([]); + + for (let c = 0; c < columns; c++) { + data[r].push(`${Math.floor(Math.random() * 999) + 1}`); + } + } + + return data; +} + +/** + * A simple state object for the demo. + * + * @type {object} + */ +const state = { + currentSheet: null, +}; + +/** + * Input configuration and definition. + * + * @type {object} + */ +const inputConfig = { + 'add-sheet': { + inputs: [ + { + type: 'text', + placeholder: 'Sheet name', + }, + ], + buttonText: 'Add Sheet', + disclaimer: + 'For the sake of this demo, the new sheets will be filled with random data.', + }, + 'remove-sheet': { + inputs: [ + { + type: 'text', + placeholder: 'Sheet name', + }, + ], + buttonText: 'Remove Sheet', + }, + 'add-rows': { + inputs: [ + { + type: 'number', + placeholder: 'Index', + }, + { + type: 'number', + placeholder: 'Amount', + }, + ], + buttonText: 'Add Rows', + }, + 'add-columns': { + inputs: [ + { + type: 'number', + placeholder: 'Index', + }, + { + type: 'number', + placeholder: 'Amount', + }, + ], + buttonText: 'Add Columns', + }, + 'remove-rows': { + inputs: [ + { + type: 'number', + placeholder: 'Index', + }, + { + type: 'number', + placeholder: 'Amount', + }, + ], + buttonText: 'Remove Rows', + }, + 'remove-columns': { + inputs: [ + { + type: 'number', + placeholder: 'Index', + }, + { + type: 'number', + placeholder: 'Amount', + }, + ], + buttonText: 'Remove Columns', + }, + 'get-value': { + inputs: [ + { + type: 'text', + placeholder: 'Cell Address', + }, + { + type: 'text', + disabled: 'disabled', + placeholder: '', + }, + ], + disclaimer: 'Cell addresses format examples: A1, B4, C6.', + buttonText: 'Get Value', + }, + 'set-value': { + inputs: [ + { + type: 'text', + placeholder: 'Cell Address', + }, + { + type: 'text', + placeholder: 'Value', + }, + ], + disclaimer: 'Cell addresses format examples: A1, B4, C6.', + buttonText: 'Set Value', + }, +}; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: 'gpl-v3', +}); + +// Add a new sheet and get its id. +state.currentSheet = 'InitialSheet'; + +const sheetName = hf.addSheet(state.currentSheet); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setSheetContent(sheetId, getSampleData(5, 5)); + +/** + * Fill the HTML table with data. + * + * @param {string} sheetName Sheet name. + */ +function renderTable(sheetName) { + const sheetId = hf.getSheetId(state.currentSheet); + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const isEmpty = hf.isCellEmpty(cellAddress); + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = cellHasFormula; + let cellValue = ''; + + if (isEmpty) { + cellValue = ''; + } else if (!showFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ''; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Updates the sheet dropdown. + */ +function updateSheetDropdown() { + const sheetNames = hf.getSheetNames(); + const sheetDropdownDOM = document.querySelector('#sheet-select'); + let dropdownContent = ''; + + sheetDropdownDOM.innerHTML = ''; + sheetNames.forEach((sheetName) => { + const isCurrent = sheetName === state.currentSheet; + + dropdownContent += ``; + }); + sheetDropdownDOM.innerHTML = dropdownContent; +} + +/** + * Update the form to the provided action. + * + * @param {string} action Action chosen from the dropdown. + */ +function updateForm(action) { + const inputsDOM = document.querySelector('#inputs'); + const submitButtonDOM = document.querySelector('#inputs button'); + const allInputsDOM = document.querySelectorAll('#inputs input'); + const disclaimerDOM = document.querySelector('#disclaimer'); + + // Hide all inputs + allInputsDOM.forEach((input) => { + input.style.display = 'none'; + input.value = ''; + input.disabled = false; + }); + inputConfig[action].inputs.forEach((inputCfg, index) => { + const inputDOM = document.querySelector(`#input-${index + 1}`); + + // Show only those needed + inputDOM.style.display = 'block'; + + for (const [attribute, value] of Object.entries(inputCfg)) { + inputDOM.setAttribute(attribute, value); + } + }); + submitButtonDOM.innerText = inputConfig[action].buttonText; + + if (inputConfig[action].disclaimer) { + disclaimerDOM.innerHTML = inputConfig[action].disclaimer; + } else { + disclaimerDOM.innerHTML = ' '; + } + + inputsDOM.style.display = 'block'; +} + +/** + * Add the error overlay. + * + * @param {string} message Error message. + */ +function renderError(message) { + const inputsDOM = document.querySelector('#inputs'); + const errorDOM = document.querySelector('#error-message'); + + if (inputsDOM.className.indexOf('error') === -1) { + inputsDOM.className += ' error'; + } + + errorDOM.innerText = message; + errorDOM.style.display = 'block'; +} + +/** + * Clear the error overlay. + */ +function clearError() { + const inputsDOM = document.querySelector('#inputs'); + const errorDOM = document.querySelector('#error-message'); + + inputsDOM.className = inputsDOM.className.replace(' error', ''); + errorDOM.innerText = ''; + errorDOM.style.display = 'none'; +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const sheetDropdown = document.querySelector('#sheet-select'); + const actionDropdown = document.querySelector('#action-select'); + const submitButton = document.querySelector('#inputs button'); + + sheetDropdown.addEventListener('change', (event) => { + state.currentSheet = event.target.value; + clearError(); + renderTable(); + }); + actionDropdown.addEventListener('change', (event) => { + clearError(); + updateForm(event.target.value); + }); + submitButton.addEventListener('click', (event) => { + const action = document.querySelector('#action-select').value; + + doAction(action); + }); +} + +/** + * Perform the wanted action. + * + * @param {string} action Action to perform. + */ +function doAction(action) { + let cellAddress = null; + let inputValues = [ + document.querySelector('#input-1').value || void 0, + document.querySelector('#input-2').value || void 0, + ]; + + clearError(); + + switch (action) { + case 'add-sheet': + state.currentSheet = hf.addSheet(inputValues[0]); + handleError(() => { + hf.setSheetContent( + hf.getSheetId(state.currentSheet), + getSampleData(5, 5) + ); + }); + updateSheetDropdown(); + renderTable(); + + break; + case 'remove-sheet': + handleError(() => { + hf.removeSheet(hf.getSheetId(inputValues[0])); + }); + + if (state.currentSheet === inputValues[0]) { + state.currentSheet = hf.getSheetNames()[0]; + renderTable(); + } + + updateSheetDropdown(); + + break; + case 'add-rows': + handleError(() => { + hf.addRows(hf.getSheetId(state.currentSheet), [ + parseInt(inputValues[0], 10), + parseInt(inputValues[1], 10), + ]); + }); + renderTable(); + + break; + case 'add-columns': + handleError(() => { + hf.addColumns(hf.getSheetId(state.currentSheet), [ + parseInt(inputValues[0], 10), + parseInt(inputValues[1], 10), + ]); + }); + renderTable(); + + break; + case 'remove-rows': + handleError(() => { + hf.removeRows(hf.getSheetId(state.currentSheet), [ + parseInt(inputValues[0], 10), + parseInt(inputValues[1], 10), + ]); + }); + renderTable(); + + break; + case 'remove-columns': + handleError(() => { + hf.removeColumns(hf.getSheetId(state.currentSheet), [ + parseInt(inputValues[0], 10), + parseInt(inputValues[1], 10), + ]); + }); + renderTable(); + + break; + case 'get-value': + const resultDOM = document.querySelector('#input-2'); + + cellAddress = handleError(() => { + return hf.simpleCellAddressFromString( + inputValues[0], + hf.getSheetId(state.currentSheet) + ); + }, 'Invalid cell address format.'); + + if (cellAddress !== null) { + resultDOM.value = handleError(() => { + return hf.getCellValue(cellAddress); + }); + } + + break; + case 'set-value': + cellAddress = handleError(() => { + return hf.simpleCellAddressFromString( + inputValues[0], + hf.getSheetId(state.currentSheet) + ); + }, 'Invalid cell address format.'); + + if (cellAddress !== null) { + handleError(() => { + hf.setCellContents(cellAddress, inputValues[1]); + }); + } + + renderTable(); + + break; + default: + } +} + +/** + * Handle the HF errors. + * + * @param {Function} tryFunc Function to handle. + * @param {string} [message] Optional forced error message. + */ +function handleError(tryFunc, message = null) { + let result = null; + + try { + result = tryFunc(); + } catch (e) { + if (e instanceof Error) { + renderError(message || e.message); + } else { + renderError('Something went wrong'); + } + } + + return result; +} + +// // Bind the UI events. +bindEvents(); +// Render the table. +renderTable(); +// Refresh the sheet dropdown list +updateSheetDropdown(); diff --git a/docs/examples/basic-operations/example1.ts b/docs/examples/basic-operations/example1.ts new file mode 100644 index 0000000000..bc56663ffc --- /dev/null +++ b/docs/examples/basic-operations/example1.ts @@ -0,0 +1,464 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +/* end:skip-in-compilation */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +const ANIMATION_ENABLED = true; + +/** + * Return sample data for the provided number of rows and columns. + * + * @param {number} rows Amount of rows to create. + * @param {number} columns Amount of columns to create. + * @returns {string[][]} + */ +function getSampleData(rows, columns) { + const data = []; + + for (let r = 0; r < rows; r++) { + data.push([]); + + for (let c = 0; c < columns; c++) { + data[r].push(`${Math.floor(Math.random() * 999) + 1}`); + } + } + + return data; +} + +/** + * A simple state object for the demo. + * + * @type {object} + */ +const state = { + currentSheet: null +}; + +/** + * Input configuration and definition. + * + * @type {object} + */ +const inputConfig = { + "add-sheet": { + inputs: [ + { + type: "text", + placeholder: "Sheet name" + } + ], + buttonText: "Add Sheet", + disclaimer: + "For the sake of this demo, the new sheets will be filled with random data." + }, + "remove-sheet": { + inputs: [ + { + type: "text", + placeholder: "Sheet name" + } + ], + buttonText: "Remove Sheet" + }, + "add-rows": { + inputs: [ + { + type: "number", + placeholder: "Index" + }, + { + type: "number", + placeholder: "Amount" + } + ], + buttonText: "Add Rows" + }, + "add-columns": { + inputs: [ + { + type: "number", + placeholder: "Index" + }, + { + type: "number", + placeholder: "Amount" + } + ], + buttonText: "Add Columns" + }, + "remove-rows": { + inputs: [ + { + type: "number", + placeholder: "Index" + }, + { + type: "number", + placeholder: "Amount" + } + ], + buttonText: "Remove Rows" + }, + "remove-columns": { + inputs: [ + { + type: "number", + placeholder: "Index" + }, + { + type: "number", + placeholder: "Amount" + } + ], + buttonText: "Remove Columns" + }, + "get-value": { + inputs: [ + { + type: "text", + placeholder: "Cell Address" + }, + { + type: "text", + disabled: "disabled", + placeholder: "" + } + ], + disclaimer: "Cell addresses format examples: A1, B4, C6.", + buttonText: "Get Value" + }, + "set-value": { + inputs: [ + { + type: "text", + placeholder: "Cell Address" + }, + { + type: "text", + placeholder: "Value" + } + ], + disclaimer: "Cell addresses format examples: A1, B4, C6.", + buttonText: "Set Value" + } +}; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +state.currentSheet = "InitialSheet"; +const sheetName = hf.addSheet(state.currentSheet); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setSheetContent(sheetId, getSampleData(5, 5)); + +/** + * Fill the HTML table with data. + * + * @param {string} sheetName Sheet name. + */ +function renderTable(sheetName) { + const sheetId = hf.getSheetId(state.currentSheet); + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const isEmpty = hf.isCellEmpty(cellAddress); + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = cellHasFormula; + let cellValue = ""; + + if (isEmpty) { + cellValue = ""; + } else if (!showFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ""; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Updates the sheet dropdown. + */ +function updateSheetDropdown() { + const sheetNames = hf.getSheetNames(); + const sheetDropdownDOM = document.querySelector("#sheet-select"); + let dropdownContent = ""; + + sheetDropdownDOM.innerHTML = ""; + + sheetNames.forEach(sheetName => { + const isCurrent = sheetName === state.currentSheet; + dropdownContent += ``; + }); + + sheetDropdownDOM.innerHTML = dropdownContent; +} + +/** + * Update the form to the provided action. + * + * @param {string} action Action chosen from the dropdown. + */ +function updateForm(action) { + const inputsDOM = document.querySelector("#inputs"); + const submitButtonDOM = document.querySelector("#inputs button"); + const allInputsDOM = document.querySelectorAll("#inputs input"); + const disclaimerDOM = document.querySelector("#disclaimer"); + + // Hide all inputs + allInputsDOM.forEach(input => { + input.style.display = "none"; + input.value = ""; + input.disabled = false; + }); + + inputConfig[action].inputs.forEach((inputCfg, index) => { + const inputDOM = document.querySelector(`#input-${index + 1}`); + + // Show only those needed + inputDOM.style.display = "block"; + + for (const [attribute, value] of Object.entries(inputCfg)) { + inputDOM.setAttribute(attribute, value); + } + }); + + submitButtonDOM.innerText = inputConfig[action].buttonText; + + if (inputConfig[action].disclaimer) { + disclaimerDOM.innerHTML = inputConfig[action].disclaimer; + } else { + disclaimerDOM.innerHTML = " "; + } + + inputsDOM.style.display = "block"; +} + +/** + * Add the error overlay. + * + * @param {string} message Error message. + */ +function renderError(message) { + const inputsDOM = document.querySelector("#inputs"); + const errorDOM = document.querySelector("#error-message"); + + if (inputsDOM.className.indexOf("error") === -1) { + inputsDOM.className += " error"; + } + + errorDOM.innerText = message; + errorDOM.style.display = "block"; +} + +/** + * Clear the error overlay. + */ +function clearError() { + const inputsDOM = document.querySelector("#inputs"); + const errorDOM = document.querySelector("#error-message"); + + inputsDOM.className = inputsDOM.className.replace(" error", ""); + + errorDOM.innerText = ""; + errorDOM.style.display = "none"; +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const sheetDropdown = document.querySelector("#sheet-select"); + const actionDropdown = document.querySelector("#action-select"); + const submitButton = document.querySelector("#inputs button"); + + sheetDropdown.addEventListener("change", event => { + state.currentSheet = event.target.value; + + clearError(); + + renderTable(); + }); + + actionDropdown.addEventListener("change", event => { + clearError(); + + updateForm(event.target.value); + }); + + submitButton.addEventListener("click", event => { + const action = document.querySelector("#action-select").value; + + doAction(action); + }); +} + +/** + * Perform the wanted action. + * + * @param {string} action Action to perform. + */ +function doAction(action) { + let cellAddress = null; + let inputValues = [ + document.querySelector("#input-1").value || void 0, + document.querySelector("#input-2").value || void 0 + ]; + + clearError(); + + switch (action) { + case "add-sheet": + state.currentSheet = hf.addSheet(inputValues[0]); + + handleError(() => { + hf.setSheetContent(hf.getSheetId(state.currentSheet), getSampleData(5, 5)); + }); + + updateSheetDropdown(); + renderTable(); + break; + case "remove-sheet": + handleError(() => { + hf.removeSheet(hf.getSheetId(inputValues[0])); + }); + + if (state.currentSheet === inputValues[0]) { + state.currentSheet = hf.getSheetNames()[0]; + + renderTable(); + } + + updateSheetDropdown(); + break; + case "add-rows": + handleError(() => { + hf.addRows(hf.getSheetId(state.currentSheet), [ + parseInt(inputValues[0], 10), + parseInt(inputValues[1], 10) + ]); + }); + + renderTable(); + break; + case "add-columns": + handleError(() => { + hf.addColumns(hf.getSheetId(state.currentSheet), [ + parseInt(inputValues[0], 10), + parseInt(inputValues[1], 10) + ]); + }); + + renderTable(); + break; + case "remove-rows": + handleError(() => { + hf.removeRows(hf.getSheetId(state.currentSheet), [ + parseInt(inputValues[0], 10), + parseInt(inputValues[1], 10) + ]); + }); + + renderTable(); + break; + case "remove-columns": + handleError(() => { + hf.removeColumns(hf.getSheetId(state.currentSheet), [ + parseInt(inputValues[0], 10), + parseInt(inputValues[1], 10) + ]); + }); + + renderTable(); + break; + case "get-value": + const resultDOM = document.querySelector("#input-2"); + cellAddress = handleError(() => { + return hf.simpleCellAddressFromString( + inputValues[0], + hf.getSheetId(state.currentSheet) + ); + }, "Invalid cell address format."); + + if (cellAddress !== null) { + resultDOM.value = handleError(() => { + return hf.getCellValue(cellAddress); + }); + } + + break; + case "set-value": + cellAddress = handleError(() => { + return hf.simpleCellAddressFromString( + inputValues[0], + hf.getSheetId(state.currentSheet) + ); + }, "Invalid cell address format."); + + if (cellAddress !== null) { + handleError(() => { + hf.setCellContents(cellAddress, inputValues[1]); + }); + } + + renderTable(); + break; + default: + } +} + +/** + * Handle the HF errors. + * + * @param {Function} tryFunc Function to handle. + * @param {string} [message] Optional forced error message. + */ +function handleError(tryFunc, message = null) { + let result = null; + + try { + result = tryFunc(); + } catch (e) { + if (e instanceof Error) { + renderError(message || e.message); + } else { + renderError("Something went wrong"); + } + } + + return result; +} + +// // Bind the UI events. +bindEvents(); + +// Render the table. +renderTable(); + +// Refresh the sheet dropdown list +updateSheetDropdown(); diff --git a/docs/guide/basic-operations.md b/docs/guide/basic-operations.md index 9b689c6685..591308df18 100644 --- a/docs/guide/basic-operations.md +++ b/docs/guide/basic-operations.md @@ -403,10 +403,16 @@ console.log(changes); ## Demo -This demo presents several basic operations integrated with a -sample UI. +This demo presents several basic operations integrated with a sample UI. - +::: example #example1 --html 1 --css 2 --js 3 --ts 4 + +@[code](@/docs/examples/basic-operations/example1.html) + +@[code](@/docs/examples/basic-operations/example1.css) + +@[code](@/docs/examples/basic-operations/example1.js) + +@[code](@/docs/examples/basic-operations/example1.ts) + +::: From d810cd13e23665960edc3c9e136859ed2e348602 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 3 Oct 2024 13:47:14 +0200 Subject: [PATCH 19/41] Add basic-usage demo --- docs/examples/basic-usage/example1.css | 99 +++++++++++++++++++++++++ docs/examples/basic-usage/example1.html | 18 +++++ docs/examples/basic-usage/example1.js | 89 ++++++++++++++++++++++ docs/examples/basic-usage/example1.ts | 88 ++++++++++++++++++++++ docs/guide/basic-usage.md | 15 +++- 5 files changed, 305 insertions(+), 4 deletions(-) create mode 100644 docs/examples/basic-usage/example1.css create mode 100644 docs/examples/basic-usage/example1.html create mode 100644 docs/examples/basic-usage/example1.js create mode 100644 docs/examples/basic-usage/example1.ts diff --git a/docs/examples/basic-usage/example1.css b/docs/examples/basic-usage/example1.css new file mode 100644 index 0000000000..b709196967 --- /dev/null +++ b/docs/examples/basic-usage/example1.css @@ -0,0 +1,99 @@ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +.example table { + table-layout: fixed; +} + +.example table tbody tr td, +.example table tbody tr th { + overflow: hidden; + text-overflow: ellipsis; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; +} + +.example #address-preview { + font-weight: bold; +} + +.example div.result { + display: inline-block; + margin: 0 0 0 15px; +} + +.example p.data-label { + margin: 0; +} diff --git a/docs/examples/basic-usage/example1.html b/docs/examples/basic-usage/example1.html new file mode 100644 index 0000000000..1c44e338b7 --- /dev/null +++ b/docs/examples/basic-usage/example1.html @@ -0,0 +1,18 @@ +
+ +
+ result: + +
+ + + + + + + + +
+
\ No newline at end of file diff --git a/docs/examples/basic-usage/example1.js b/docs/examples/basic-usage/example1.js new file mode 100644 index 0000000000..63d20f29c0 --- /dev/null +++ b/docs/examples/basic-usage/example1.js @@ -0,0 +1,89 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; + +/* end:skip-in-compilation */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +const tableData = [['10', '20', '=SUM(A1,B1)']]; +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + precisionRounding: 10, + licenseKey: 'gpl-v3', +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet('main'); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId, + }, + tableData +); + +/** + * Fill the HTML table with data. + */ +function renderTable() { + const theadDOM = document.querySelector('.example thead'); + const tbodyDOM = document.querySelector('.example tbody'); + const { height, width } = hf.getSheetDimensions(sheetId); + let newTheadHTML = ''; + let newTbodyHTML = ''; + + for (let row = -1; row < height; row++) { + for (let col = 0; col < width; col++) { + if (row === -1) { + newTheadHTML += ``; + + continue; + } + + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + let cellValue = ''; + + if (!hf.isCellEmpty(cellAddress) && !cellHasFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ''; + } + + tbodyDOM.innerHTML = `${newTbodyHTML}`; + theadDOM.innerHTML = newTheadHTML; +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const calculateButton = document.querySelector('#calculate'); + const formulaPreview = document.querySelector('#address-preview'); + const calculationResult = document.querySelector('#result'); + const cellAddress = { sheet: sheetId, row: 0, col: 2 }; + + formulaPreview.innerText = hf.simpleCellAddressToString(cellAddress, sheetId); + calculateButton.addEventListener('click', () => { + calculationResult.innerText = hf.getCellValue(cellAddress); + }); +} + +// Bind the button events. +bindEvents(); +// Render the table. +renderTable(); diff --git a/docs/examples/basic-usage/example1.ts b/docs/examples/basic-usage/example1.ts new file mode 100644 index 0000000000..7de62f9af6 --- /dev/null +++ b/docs/examples/basic-usage/example1.ts @@ -0,0 +1,88 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +/* end:skip-in-compilation */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +const tableData = [["10", "20", "=SUM(A1,B1)"]]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + precisionRounding: 10, + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData +); + +/** + * Fill the HTML table with data. + */ +function renderTable() { + const theadDOM = document.querySelector(".example thead"); + const tbodyDOM = document.querySelector(".example tbody"); + const { height, width } = hf.getSheetDimensions(sheetId); + let newTheadHTML = ""; + let newTbodyHTML = ""; + + for (let row = -1; row < height; row++) { + for (let col = 0; col < width; col++) { + if (row === -1) { + newTheadHTML += ``; + continue; + } + + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + let cellValue = ""; + + if (!hf.isCellEmpty(cellAddress) && !cellHasFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ""; + } + + tbodyDOM.innerHTML = `${newTbodyHTML}`; + theadDOM.innerHTML = newTheadHTML; +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const calculateButton = document.querySelector("#calculate"); + const formulaPreview = document.querySelector("#address-preview"); + const calculationResult = document.querySelector("#result"); + const cellAddress = { sheet: sheetId, row: 0, col: 2 }; + + formulaPreview.innerText = hf.simpleCellAddressToString(cellAddress, sheetId); + + calculateButton.addEventListener("click", () => { + calculationResult.innerText = hf.getCellValue(cellAddress); + }); +} + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); diff --git a/docs/guide/basic-usage.md b/docs/guide/basic-usage.md index 16372888ee..d1b392c9ec 100644 --- a/docs/guide/basic-usage.md +++ b/docs/guide/basic-usage.md @@ -64,7 +64,14 @@ works. It's time to move on to a more ## Demo - +::: example #example1 --html 1 --css 2 --js 3 --ts 4 + +@[code](@/docs/examples/basic-usage/example1.html) + +@[code](@/docs/examples/basic-usage/example1.css) + +@[code](@/docs/examples/basic-usage/example1.js) + +@[code](@/docs/examples/basic-usage/example1.ts) + +::: From a1a99882918c2ba21ed4959c4222e595c7cdb192 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 3 Oct 2024 13:57:47 +0200 Subject: [PATCH 20/41] Add batch-operations demo --- docs/examples/batch-operations/example1.css | 103 ++++++++++++ docs/examples/batch-operations/example1.html | 39 +++++ docs/examples/batch-operations/example1.js | 164 ++++++++++++++++++ docs/examples/batch-operations/example1.ts | 168 +++++++++++++++++++ docs/guide/batch-operations.md | 14 +- 5 files changed, 484 insertions(+), 4 deletions(-) create mode 100644 docs/examples/batch-operations/example1.css create mode 100644 docs/examples/batch-operations/example1.html create mode 100644 docs/examples/batch-operations/example1.js create mode 100644 docs/examples/batch-operations/example1.ts diff --git a/docs/examples/batch-operations/example1.css b/docs/examples/batch-operations/example1.css new file mode 100644 index 0000000000..f72f0ce758 --- /dev/null +++ b/docs/examples/batch-operations/example1.css @@ -0,0 +1,103 @@ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +.example label { + display: inline-block; + margin-left: 5px; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + +.example table tbody tr:last-child { + font-weight: 600; +} + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +.example table { + table-layout: fixed; +} + +.example table tbody tr td, +.example table tbody tr th { + overflow: hidden; + text-overflow: ellipsis; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +.example table tbody tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/docs/examples/batch-operations/example1.html b/docs/examples/batch-operations/example1.html new file mode 100644 index 0000000000..d3ef1467e7 --- /dev/null +++ b/docs/examples/batch-operations/example1.html @@ -0,0 +1,39 @@ +
+
+
+ + +
+
+
+
+ + +
+
+
+ + + + + + + + + + + + + + + + + + +
NameYear_1Year_2AverageSum
+
+
\ No newline at end of file diff --git a/docs/examples/batch-operations/example1.js b/docs/examples/batch-operations/example1.js new file mode 100644 index 0000000000..2cd2c5a4cd --- /dev/null +++ b/docs/examples/batch-operations/example1.js @@ -0,0 +1,164 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; + +/* end:skip-in-compilation */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +/** + * Initial table data. + */ +const tableData = [ + ['Greg Black', 4.66, '=B1*1.3', '=AVERAGE(B1:C1)', '=SUM(B1:C1)'], + ['Anne Carpenter', 5.25, '=$B$2*30%', '=AVERAGE(B2:C2)', '=SUM(B2:C2)'], + ['Natalie Dem', 3.59, '=B3*2.7+2+1', '=AVERAGE(B3:C3)', '=SUM(B3:C3)'], + ['John Sieg', 12.51, '=B4*(1.22+1)', '=AVERAGE(B4:C4)', '=SUM(B4:C4)'], + [ + 'Chris Aklips', + 7.63, + '=B5*1.1*SUM(10,20)+1', + '=AVERAGE(B5:C5)', + '=SUM(B5:C5)', + ], +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: 'gpl-v3', +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet('main'); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId, + }, + tableData +); +// Add named expressions for the "TOTAL" row. +hf.addNamedExpression('Year_1', '=SUM(main!$B$1:main!$B$5)'); +hf.addNamedExpression('Year_2', '=SUM(main!$C$1:main!$C$5)'); + +const ANIMATION_ENABLED = true; + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const totals = ['=SUM(Year_1)', '=SUM(Year_2)']; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + let totalRowsHTML = ''; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = ''; + + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + + if (!isNaN(cellValue)) { + cellValue = cellValue.toFixed(2); + } + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ''; + } + + totalRowsHTML = ` + TOTAL + + ${ + calculated + ? hf.calculateFormula(totals[0], sheetId).toFixed(2) + : totals[0] + } + + + ${ + calculated + ? hf.calculateFormula(totals[1], sheetId).toFixed(2) + : totals[1] + } + + + `; + newTbodyHTML += totalRowsHTML; + tbodyDOM.innerHTML = newTbodyHTML; +} + +let IS_CALCULATED = false; + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector('#run'); + const resetButton = document.querySelector('#reset'); + const calculatedCheckbox = document.querySelector('#isCalculated'); + + runButton.addEventListener('click', () => { + runBatchOperations(); + }); + resetButton.addEventListener('click', () => { + resetTableData(); + }); + calculatedCheckbox.addEventListener('change', (e) => { + if (e.target.checked) { + renderTable(true); + } else { + renderTable(); + } + + IS_CALCULATED = e.target.checked; + }); +} + +/** + * Reset the data for the table. + */ +function resetTableData() { + hf.setSheetContent(sheetId, tableData); + renderTable(IS_CALCULATED); +} + +/** + * Run batch operations. + */ +function runBatchOperations() { + hf.batch(() => { + hf.setCellContents({ col: 1, row: 0, sheet: sheetId }, [['=B4']]); + hf.setCellContents({ col: 1, row: 1, sheet: sheetId }, [['=B4']]); + hf.setCellContents({ col: 1, row: 2, sheet: sheetId }, [['=B4']]); + hf.setCellContents({ col: 1, row: 4, sheet: sheetId }, [['=B4']]); + }); + renderTable(IS_CALCULATED); +} + +// Bind the button events. +bindEvents(); +// Render the table. +renderTable(); diff --git a/docs/examples/batch-operations/example1.ts b/docs/examples/batch-operations/example1.ts new file mode 100644 index 0000000000..0e35a5eb2d --- /dev/null +++ b/docs/examples/batch-operations/example1.ts @@ -0,0 +1,168 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +/* end:skip-in-compilation */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +/** + * Initial table data. + */ +const tableData = [ + ["Greg Black", 4.66, "=B1*1.3", "=AVERAGE(B1:C1)", "=SUM(B1:C1)"], + ["Anne Carpenter", 5.25, "=$B$2*30%", "=AVERAGE(B2:C2)", "=SUM(B2:C2)"], + ["Natalie Dem", 3.59, "=B3*2.7+2+1", "=AVERAGE(B3:C3)", "=SUM(B3:C3)"], + ["John Sieg", 12.51, "=B4*(1.22+1)", "=AVERAGE(B4:C4)", "=SUM(B4:C4)"], + [ + "Chris Aklips", + 7.63, + "=B5*1.1*SUM(10,20)+1", + "=AVERAGE(B5:C5)", + "=SUM(B5:C5)" + ] +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData +); + +// Add named expressions for the "TOTAL" row. +hf.addNamedExpression("Year_1", "=SUM(main!$B$1:main!$B$5)"); +hf.addNamedExpression("Year_2", "=SUM(main!$C$1:main!$C$5)"); + +const ANIMATION_ENABLED = true; + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const totals = ["=SUM(Year_1)", "=SUM(Year_2)"]; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + let totalRowsHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = ""; + + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + + if (!isNaN(cellValue)) { + cellValue = cellValue.toFixed(2); + } + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ""; + } + + totalRowsHTML = ` + TOTAL + + ${ + calculated + ? hf.calculateFormula(totals[0], sheetId).toFixed(2) + : totals[0] + } + + + ${ + calculated + ? hf.calculateFormula(totals[1], sheetId).toFixed(2) + : totals[1] + } + + + `; + + newTbodyHTML += totalRowsHTML; + + tbodyDOM.innerHTML = newTbodyHTML; +} + +let IS_CALCULATED = false; + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector("#run"); + const resetButton = document.querySelector("#reset"); + const calculatedCheckbox = document.querySelector("#isCalculated"); + + runButton.addEventListener("click", () => { + runBatchOperations(); + }); + + resetButton.addEventListener("click", () => { + resetTableData(); + }); + + calculatedCheckbox.addEventListener("change", e => { + if (e.target.checked) { + renderTable(true); + } else { + renderTable(); + } + + IS_CALCULATED = e.target.checked; + }); +} + +/** + * Reset the data for the table. + */ +function resetTableData() { + hf.setSheetContent(sheetId, tableData); + renderTable(IS_CALCULATED); +} + +/** + * Run batch operations. + */ +function runBatchOperations() { + hf.batch(() => { + hf.setCellContents({ col: 1, row: 0, sheet: sheetId }, [["=B4"]]); + hf.setCellContents({ col: 1, row: 1, sheet: sheetId }, [["=B4"]]); + hf.setCellContents({ col: 1, row: 2, sheet: sheetId }, [["=B4"]]); + hf.setCellContents({ col: 1, row: 4, sheet: sheetId }, [["=B4"]]); + }); + + renderTable(IS_CALCULATED); +} + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); diff --git a/docs/guide/batch-operations.md b/docs/guide/batch-operations.md index 835e2087e4..5e3d9a5694 100644 --- a/docs/guide/batch-operations.md +++ b/docs/guide/batch-operations.md @@ -122,8 +122,14 @@ Methods such as [`getCellValue`](../api/classes/hyperformula.md#getcellvalue), [ The [paste](../api/classes/hyperformula.md#paste) method also can't be called when batching as it reads the contents of the copied cells. ## Demo +::: example #example1 --html 1 --css 2 --js 3 --ts 4 - +@[code](@/docs/examples/batch-operations/example1.html) + +@[code](@/docs/examples/batch-operations/example1.css) + +@[code](@/docs/examples/batch-operations/example1.js) + +@[code](@/docs/examples/batch-operations/example1.ts) + +::: From 4d211524605e0e55e9a72f09b7c2884ff33d1340 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 3 Oct 2024 14:49:25 +0200 Subject: [PATCH 21/41] Add demo clipboard-operations --- docs/examples/advanced-usage/example1.js | 9 +- docs/examples/advanced-usage/example1.ts | 6 +- docs/examples/basic-operations/example1.js | 34 ++--- docs/examples/basic-operations/example1.ts | 34 ++--- docs/examples/basic-usage/example1.js | 6 +- docs/examples/basic-usage/example1.ts | 6 +- docs/examples/batch-operations/example1.js | 6 +- docs/examples/batch-operations/example1.ts | 6 +- .../clipboard-operations/example1.css | 100 ++++++++++++++ .../clipboard-operations/example1.html | 37 +++++ .../examples/clipboard-operations/example1.js | 130 ++++++++++++++++++ .../examples/clipboard-operations/example1.ts | 128 +++++++++++++++++ docs/examples/demo/example1.js | 4 +- docs/examples/demo/example1.ts | 4 +- docs/guide/batch-operations.md | 1 + docs/guide/clipboard-operations.md | 15 +- 16 files changed, 466 insertions(+), 60 deletions(-) create mode 100644 docs/examples/clipboard-operations/example1.css create mode 100644 docs/examples/clipboard-operations/example1.html create mode 100644 docs/examples/clipboard-operations/example1.js create mode 100644 docs/examples/clipboard-operations/example1.ts diff --git a/docs/examples/advanced-usage/example1.js b/docs/examples/advanced-usage/example1.js index 952e3e6c61..375e38d719 100644 --- a/docs/examples/advanced-usage/example1.js +++ b/docs/examples/advanced-usage/example1.js @@ -66,7 +66,10 @@ hf.setSheetContent(hf.getSheetId(sheetInfo.formulas.sheetName), formulasData); */ function renderTable(sheetName) { const sheetId = hf.getSheetId(sheetName); - const tbodyDOM = document.querySelector(`#${sheetName}-container tbody`); + const tbodyDOM = document.querySelector( + `.example #${sheetName}-container tbody` + ); + const { height, width } = hf.getSheetDimensions(sheetId); let newTbodyHTML = ''; @@ -95,7 +98,7 @@ function renderTable(sheetName) { * Render the result block. */ function renderResult() { - const resultOutputDOM = document.querySelector('#result .output'); + const resultOutputDOM = document.querySelector('.example #result .output'); const cellAddress = hf.simpleCellAddressFromString( `${sheetInfo.formulas.sheetName}!A1`, hf.getSheetId(sheetInfo.formulas.sheetName) @@ -110,7 +113,7 @@ function renderResult() { * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector('#run'); + const runButton = document.querySelector('.example #run'); runButton.addEventListener('click', () => { renderResult(); diff --git a/docs/examples/advanced-usage/example1.ts b/docs/examples/advanced-usage/example1.ts index e4849ce3bc..beb01e07c4 100644 --- a/docs/examples/advanced-usage/example1.ts +++ b/docs/examples/advanced-usage/example1.ts @@ -65,7 +65,7 @@ hf.setSheetContent(hf.getSheetId(sheetInfo.formulas.sheetName), formulasData); */ function renderTable(sheetName) { const sheetId = hf.getSheetId(sheetName); - const tbodyDOM = document.querySelector(`#${sheetName}-container tbody`); + const tbodyDOM = document.querySelector(`.example #${sheetName}-container tbody`); const { height, width } = hf.getSheetDimensions(sheetId); let newTbodyHTML = ""; @@ -94,7 +94,7 @@ function renderTable(sheetName) { * Render the result block. */ function renderResult() { - const resultOutputDOM = document.querySelector("#result .output"); + const resultOutputDOM = document.querySelector(".example #result .output"); const cellAddress = hf.simpleCellAddressFromString( `${sheetInfo.formulas.sheetName}!A1`, hf.getSheetId(sheetInfo.formulas.sheetName) ); @@ -108,7 +108,7 @@ function renderResult() { * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector("#run"); + const runButton = document.querySelector(".example #run"); runButton.addEventListener("click", () => { renderResult(); diff --git a/docs/examples/basic-operations/example1.js b/docs/examples/basic-operations/example1.js index 9485c587ff..f0630133cc 100644 --- a/docs/examples/basic-operations/example1.js +++ b/docs/examples/basic-operations/example1.js @@ -208,7 +208,7 @@ function renderTable(sheetName) { */ function updateSheetDropdown() { const sheetNames = hf.getSheetNames(); - const sheetDropdownDOM = document.querySelector('#sheet-select'); + const sheetDropdownDOM = document.querySelector('.example #sheet-select'); let dropdownContent = ''; sheetDropdownDOM.innerHTML = ''; @@ -228,10 +228,10 @@ function updateSheetDropdown() { * @param {string} action Action chosen from the dropdown. */ function updateForm(action) { - const inputsDOM = document.querySelector('#inputs'); - const submitButtonDOM = document.querySelector('#inputs button'); - const allInputsDOM = document.querySelectorAll('#inputs input'); - const disclaimerDOM = document.querySelector('#disclaimer'); + const inputsDOM = document.querySelector('.example #inputs'); + const submitButtonDOM = document.querySelector('.example #inputs button'); + const allInputsDOM = document.querySelectorAll('.example #inputs input'); + const disclaimerDOM = document.querySelector('.example #disclaimer'); // Hide all inputs allInputsDOM.forEach((input) => { @@ -240,7 +240,7 @@ function updateForm(action) { input.disabled = false; }); inputConfig[action].inputs.forEach((inputCfg, index) => { - const inputDOM = document.querySelector(`#input-${index + 1}`); + const inputDOM = document.querySelector(`.example #input-${index + 1}`); // Show only those needed inputDOM.style.display = 'block'; @@ -266,8 +266,8 @@ function updateForm(action) { * @param {string} message Error message. */ function renderError(message) { - const inputsDOM = document.querySelector('#inputs'); - const errorDOM = document.querySelector('#error-message'); + const inputsDOM = document.querySelector('.example #inputs'); + const errorDOM = document.querySelector('.example #error-message'); if (inputsDOM.className.indexOf('error') === -1) { inputsDOM.className += ' error'; @@ -281,8 +281,8 @@ function renderError(message) { * Clear the error overlay. */ function clearError() { - const inputsDOM = document.querySelector('#inputs'); - const errorDOM = document.querySelector('#error-message'); + const inputsDOM = document.querySelector('.example #inputs'); + const errorDOM = document.querySelector('.example #error-message'); inputsDOM.className = inputsDOM.className.replace(' error', ''); errorDOM.innerText = ''; @@ -293,9 +293,9 @@ function clearError() { * Bind the events to the buttons. */ function bindEvents() { - const sheetDropdown = document.querySelector('#sheet-select'); - const actionDropdown = document.querySelector('#action-select'); - const submitButton = document.querySelector('#inputs button'); + const sheetDropdown = document.querySelector('.example #sheet-select'); + const actionDropdown = document.querySelector('.example #action-select'); + const submitButton = document.querySelector('.example #inputs button'); sheetDropdown.addEventListener('change', (event) => { state.currentSheet = event.target.value; @@ -307,7 +307,7 @@ function bindEvents() { updateForm(event.target.value); }); submitButton.addEventListener('click', (event) => { - const action = document.querySelector('#action-select').value; + const action = document.querySelector('.example #action-select').value; doAction(action); }); @@ -321,8 +321,8 @@ function bindEvents() { function doAction(action) { let cellAddress = null; let inputValues = [ - document.querySelector('#input-1').value || void 0, - document.querySelector('#input-2').value || void 0, + document.querySelector('.example #input-1').value || void 0, + document.querySelector('.example #input-2').value || void 0, ]; clearError(); @@ -394,7 +394,7 @@ function doAction(action) { break; case 'get-value': - const resultDOM = document.querySelector('#input-2'); + const resultDOM = document.querySelector('.example #input-2'); cellAddress = handleError(() => { return hf.simpleCellAddressFromString( diff --git a/docs/examples/basic-operations/example1.ts b/docs/examples/basic-operations/example1.ts index bc56663ffc..27d4188bcd 100644 --- a/docs/examples/basic-operations/example1.ts +++ b/docs/examples/basic-operations/example1.ts @@ -204,7 +204,7 @@ function renderTable(sheetName) { */ function updateSheetDropdown() { const sheetNames = hf.getSheetNames(); - const sheetDropdownDOM = document.querySelector("#sheet-select"); + const sheetDropdownDOM = document.querySelector(".example #sheet-select"); let dropdownContent = ""; sheetDropdownDOM.innerHTML = ""; @@ -225,10 +225,10 @@ function updateSheetDropdown() { * @param {string} action Action chosen from the dropdown. */ function updateForm(action) { - const inputsDOM = document.querySelector("#inputs"); - const submitButtonDOM = document.querySelector("#inputs button"); - const allInputsDOM = document.querySelectorAll("#inputs input"); - const disclaimerDOM = document.querySelector("#disclaimer"); + const inputsDOM = document.querySelector(".example #inputs"); + const submitButtonDOM = document.querySelector(".example #inputs button"); + const allInputsDOM = document.querySelectorAll(".example #inputs input"); + const disclaimerDOM = document.querySelector(".example #disclaimer"); // Hide all inputs allInputsDOM.forEach(input => { @@ -238,7 +238,7 @@ function updateForm(action) { }); inputConfig[action].inputs.forEach((inputCfg, index) => { - const inputDOM = document.querySelector(`#input-${index + 1}`); + const inputDOM = document.querySelector(`.example #input-${index + 1}`); // Show only those needed inputDOM.style.display = "block"; @@ -265,8 +265,8 @@ function updateForm(action) { * @param {string} message Error message. */ function renderError(message) { - const inputsDOM = document.querySelector("#inputs"); - const errorDOM = document.querySelector("#error-message"); + const inputsDOM = document.querySelector(".example #inputs"); + const errorDOM = document.querySelector(".example #error-message"); if (inputsDOM.className.indexOf("error") === -1) { inputsDOM.className += " error"; @@ -280,8 +280,8 @@ function renderError(message) { * Clear the error overlay. */ function clearError() { - const inputsDOM = document.querySelector("#inputs"); - const errorDOM = document.querySelector("#error-message"); + const inputsDOM = document.querySelector(".example #inputs"); + const errorDOM = document.querySelector(".example #error-message"); inputsDOM.className = inputsDOM.className.replace(" error", ""); @@ -293,9 +293,9 @@ function clearError() { * Bind the events to the buttons. */ function bindEvents() { - const sheetDropdown = document.querySelector("#sheet-select"); - const actionDropdown = document.querySelector("#action-select"); - const submitButton = document.querySelector("#inputs button"); + const sheetDropdown = document.querySelector(".example #sheet-select"); + const actionDropdown = document.querySelector(".example #action-select"); + const submitButton = document.querySelector(".example #inputs button"); sheetDropdown.addEventListener("change", event => { state.currentSheet = event.target.value; @@ -312,7 +312,7 @@ function bindEvents() { }); submitButton.addEventListener("click", event => { - const action = document.querySelector("#action-select").value; + const action = document.querySelector(".example #action-select").value; doAction(action); }); @@ -326,8 +326,8 @@ function bindEvents() { function doAction(action) { let cellAddress = null; let inputValues = [ - document.querySelector("#input-1").value || void 0, - document.querySelector("#input-2").value || void 0 + document.querySelector(".example #input-1").value || void 0, + document.querySelector(".example #input-2").value || void 0 ]; clearError(); @@ -397,7 +397,7 @@ function doAction(action) { renderTable(); break; case "get-value": - const resultDOM = document.querySelector("#input-2"); + const resultDOM = document.querySelector(".example #input-2"); cellAddress = handleError(() => { return hf.simpleCellAddressFromString( inputValues[0], diff --git a/docs/examples/basic-usage/example1.js b/docs/examples/basic-usage/example1.js index 63d20f29c0..8b426855d2 100644 --- a/docs/examples/basic-usage/example1.js +++ b/docs/examples/basic-usage/example1.js @@ -72,9 +72,9 @@ function renderTable() { * Bind the events to the buttons. */ function bindEvents() { - const calculateButton = document.querySelector('#calculate'); - const formulaPreview = document.querySelector('#address-preview'); - const calculationResult = document.querySelector('#result'); + const calculateButton = document.querySelector('.example #calculate'); + const formulaPreview = document.querySelector('.example #address-preview'); + const calculationResult = document.querySelector('.example #result'); const cellAddress = { sheet: sheetId, row: 0, col: 2 }; formulaPreview.innerText = hf.simpleCellAddressToString(cellAddress, sheetId); diff --git a/docs/examples/basic-usage/example1.ts b/docs/examples/basic-usage/example1.ts index 7de62f9af6..4ec0962143 100644 --- a/docs/examples/basic-usage/example1.ts +++ b/docs/examples/basic-usage/example1.ts @@ -69,9 +69,9 @@ function renderTable() { * Bind the events to the buttons. */ function bindEvents() { - const calculateButton = document.querySelector("#calculate"); - const formulaPreview = document.querySelector("#address-preview"); - const calculationResult = document.querySelector("#result"); + const calculateButton = document.querySelector(".example #calculate"); + const formulaPreview = document.querySelector(".example #address-preview"); + const calculationResult = document.querySelector(".example #result"); const cellAddress = { sheet: sheetId, row: 0, col: 2 }; formulaPreview.innerText = hf.simpleCellAddressToString(cellAddress, sheetId); diff --git a/docs/examples/batch-operations/example1.js b/docs/examples/batch-operations/example1.js index 2cd2c5a4cd..4daa2bfce9 100644 --- a/docs/examples/batch-operations/example1.js +++ b/docs/examples/batch-operations/example1.js @@ -116,9 +116,9 @@ let IS_CALCULATED = false; * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector('#run'); - const resetButton = document.querySelector('#reset'); - const calculatedCheckbox = document.querySelector('#isCalculated'); + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); + const calculatedCheckbox = document.querySelector('.example #isCalculated'); runButton.addEventListener('click', () => { runBatchOperations(); diff --git a/docs/examples/batch-operations/example1.ts b/docs/examples/batch-operations/example1.ts index 0e35a5eb2d..ea353e41dc 100644 --- a/docs/examples/batch-operations/example1.ts +++ b/docs/examples/batch-operations/example1.ts @@ -116,9 +116,9 @@ let IS_CALCULATED = false; * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector("#run"); - const resetButton = document.querySelector("#reset"); - const calculatedCheckbox = document.querySelector("#isCalculated"); + const runButton = document.querySelector(".example #run"); + const resetButton = document.querySelector(".example #reset"); + const calculatedCheckbox = document.querySelector(".example #isCalculated"); runButton.addEventListener("click", () => { runBatchOperations(); diff --git a/docs/examples/clipboard-operations/example1.css b/docs/examples/clipboard-operations/example1.css new file mode 100644 index 0000000000..894f36f33e --- /dev/null +++ b/docs/examples/clipboard-operations/example1.css @@ -0,0 +1,100 @@ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +.example label { + display: inline-block; + margin-left: 5px; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +.example table { + table-layout: fixed; +} + +.example table tbody tr td, +.example table tbody tr th { + overflow: hidden; + text-overflow: ellipsis; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +.example table tbody tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/docs/examples/clipboard-operations/example1.html b/docs/examples/clipboard-operations/example1.html new file mode 100644 index 0000000000..13b687946e --- /dev/null +++ b/docs/examples/clipboard-operations/example1.html @@ -0,0 +1,37 @@ +
+
+
+ + + +
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + +
NameSurnameBoth
+
diff --git a/docs/examples/clipboard-operations/example1.js b/docs/examples/clipboard-operations/example1.js new file mode 100644 index 0000000000..75db3f5ca4 --- /dev/null +++ b/docs/examples/clipboard-operations/example1.js @@ -0,0 +1,130 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; + +/* end:skip-in-compilation */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +/** + * Initial table data. + */ +const tableData = [ + ['Greg', 'Black', '=CONCATENATE(A1, " ",B1)'], + ['Anne', 'Carpenter', '=CONCATENATE(A2, " ", B2)'], + ['Chris', 'Aklips', '=CONCATENATE(A3, " ",B3)'], +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: 'gpl-v3', +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet('main'); +const sheetId = hf.getSheetId(sheetName); + +/** + * Reinitialize the HF data. + */ +function reinitializeData() { + hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId, + }, + tableData + ); +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const copyButton = document.querySelector('.example #copy'); + const pasteButton = document.querySelector('.example #paste'); + const resetButton = document.querySelector('.example #reset'); + + copyButton.addEventListener('click', () => { + copy(); + updateCopyInfo('Second row copied'); + }); + pasteButton.addEventListener('click', () => { + paste(); + updateCopyInfo('Pasted into the first row'); + }); + resetButton.addEventListener('click', () => { + reinitializeData(); + updateCopyInfo(''); + renderTable(); + }); +} + +/** + * Copy the second row. + */ +function copy() { + return hf.copy({ + start: { sheet: 0, col: 0, row: 1 }, + end: { sheet: 0, col: 2, row: 1 }, + }); +} + +/** + * Paste the HF clipboard into the first row. + */ +function paste() { + hf.paste({ sheet: 0, col: 0, row: 0 }); + renderTable(); +} + +const ANIMATION_ENABLED = true; + +/** + * Fill the HTML table with data. + */ +function renderTable() { + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + let cellValue = ''; + + if (!hf.isCellEmpty(cellAddress)) { + cellValue = hf.getCellValue(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ''; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Update the information about the copy/paste action. + * + * @param {string} message Message to display. + */ +function updateCopyInfo(message) { + const copyInfoDOM = document.querySelector('.example #copyInfo'); + + copyInfoDOM.innerText = message; +} + +// Fill the HyperFormula sheet with data. +reinitializeData(); +// Bind the button events. +bindEvents(); +// Render the table. +renderTable(); diff --git a/docs/examples/clipboard-operations/example1.ts b/docs/examples/clipboard-operations/example1.ts new file mode 100644 index 0000000000..476b4253b9 --- /dev/null +++ b/docs/examples/clipboard-operations/example1.ts @@ -0,0 +1,128 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +/* end:skip-in-compilation */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +/** + * Initial table data. + */ +const tableData = [ + ["Greg", "Black", '=CONCATENATE(A1, " ",B1)'], + ["Anne", "Carpenter", '=CONCATENATE(A2, " ", B2)'], + ["Chris", "Aklips", '=CONCATENATE(A3, " ",B3)'] +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +/** + * Reinitialize the HF data. + */ +function reinitializeData() { + hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData + ); +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const copyButton = document.querySelector(".example #copy"); + const pasteButton = document.querySelector(".example #paste"); + const resetButton = document.querySelector(".example #reset"); + + copyButton.addEventListener("click", () => { + copy(); + updateCopyInfo("Second row copied"); + }); + + pasteButton.addEventListener("click", () => { + paste(); + updateCopyInfo("Pasted into the first row"); + }); + + resetButton.addEventListener("click", () => { + reinitializeData(); + updateCopyInfo(""); + renderTable(); + }); +} + +/** + * Copy the second row. + */ +function copy() { + return hf.copy({start: { sheet: 0, col: 0, row: 1 }, end: { sheet: 0, col: 2, row: 1 }}); +} + +/** + * Paste the HF clipboard into the first row. + */ +function paste() { + hf.paste({ sheet: 0, col: 0, row: 0 }); + renderTable(); +} + +const ANIMATION_ENABLED = true; + +/** + * Fill the HTML table with data. + */ +function renderTable() { + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + let cellValue = ""; + + if (!hf.isCellEmpty(cellAddress)) { + cellValue = hf.getCellValue(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ""; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Update the information about the copy/paste action. + * + * @param {string} message Message to display. + */ +function updateCopyInfo(message) { + const copyInfoDOM = document.querySelector(".example #copyInfo"); + + copyInfoDOM.innerText = message; +} + +// Fill the HyperFormula sheet with data. +reinitializeData(); + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); diff --git a/docs/examples/demo/example1.js b/docs/examples/demo/example1.js index 25840b2305..b582ed84d6 100644 --- a/docs/examples/demo/example1.js +++ b/docs/examples/demo/example1.js @@ -45,8 +45,8 @@ hf.addNamedExpression('Year_2', '=SUM(main!$C$1:main!$C$5)'); // Bind the events to the buttons. function bindEvents() { - const runButton = document.querySelector('#run'); - const resetButton = document.querySelector('#reset'); + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); runButton.addEventListener('click', () => { runCalculations(); diff --git a/docs/examples/demo/example1.ts b/docs/examples/demo/example1.ts index f306f12ec0..9f6d341cb0 100644 --- a/docs/examples/demo/example1.ts +++ b/docs/examples/demo/example1.ts @@ -32,8 +32,8 @@ hf.addNamedExpression("Year_2", "=SUM(main!$C$1:main!$C$5)"); // Bind the events to the buttons. function bindEvents() { - const runButton = document.querySelector("#run"); - const resetButton = document.querySelector("#reset"); + const runButton = document.querySelector(".example #run"); + const resetButton = document.querySelector(".example #reset"); runButton.addEventListener("click", () => { runCalculations(); diff --git a/docs/guide/batch-operations.md b/docs/guide/batch-operations.md index 5e3d9a5694..54596320ae 100644 --- a/docs/guide/batch-operations.md +++ b/docs/guide/batch-operations.md @@ -122,6 +122,7 @@ Methods such as [`getCellValue`](../api/classes/hyperformula.md#getcellvalue), [ The [paste](../api/classes/hyperformula.md#paste) method also can't be called when batching as it reads the contents of the copied cells. ## Demo + ::: example #example1 --html 1 --css 2 --js 3 --ts 4 @[code](@/docs/examples/batch-operations/example1.html) diff --git a/docs/guide/clipboard-operations.md b/docs/guide/clipboard-operations.md index bf6ae78bd8..0360f0afd5 100644 --- a/docs/guide/clipboard-operations.md +++ b/docs/guide/clipboard-operations.md @@ -112,7 +112,14 @@ Depending on what was cut, the data is stored as: ## Demo - \ No newline at end of file +::: example #example1 --html 1 --css 2 --js 3 --ts 4 + +@[code](@/docs/examples/clipboard-operations/example1.html) + +@[code](@/docs/examples/clipboard-operations/example1.css) + +@[code](@/docs/examples/clipboard-operations/example1.js) + +@[code](@/docs/examples/clipboard-operations/example1.ts) + +::: \ No newline at end of file From c6f4ccc755bb3b2a9382b2a8a5abd6db504bb21d Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 3 Oct 2024 16:45:23 +0200 Subject: [PATCH 22/41] Changed the custom-functions demo to use Codesandbox instead of Stackblitz --- docs/guide/custom-functions.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/guide/custom-functions.md b/docs/guide/custom-functions.md index 9726b2a40a..14ace0edd4 100644 --- a/docs/guide/custom-functions.md +++ b/docs/guide/custom-functions.md @@ -363,8 +363,11 @@ This demo contains the implementation of both the [`DOUBLE_RANGE`](#advanced-custom-function-example) custom functions. ## Function options From a327c4fe2984e80444fc17bf818383d7015866b1 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 3 Oct 2024 18:13:23 +0200 Subject: [PATCH 23/41] Add date-time demo --- docs/.vuepress/config.js | 2 + docs/.vuepress/plugins/examples/stackblitz.js | 5 +- docs/examples/date-time/example1.css | 99 +++++++++++ docs/examples/date-time/example1.html | 23 +++ docs/examples/date-time/example1.js | 154 ++++++++++++++++++ docs/examples/date-time/example1.ts | 154 ++++++++++++++++++ docs/guide/date-and-time-handling.md | 15 +- 7 files changed, 446 insertions(+), 6 deletions(-) create mode 100644 docs/examples/date-time/example1.css create mode 100644 docs/examples/date-time/example1.html create mode 100644 docs/examples/date-time/example1.js create mode 100644 docs/examples/date-time/example1.ts diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index de3b2460e0..a7c97643e0 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -14,6 +14,8 @@ module.exports = { head: [ // Import HF (required for the examples) [ 'script', { src: 'https://cdn.jsdelivr.net/npm/hyperformula/dist/hyperformula.full.min.js' } ], + // Import moment (required for the examples) + [ 'script', { src: 'https://cdn.jsdelivr.net/npm/moment/moment.min.js' } ], // Google Tag Manager, an extra element within the `ssr.html` file. ['script', {}, ` (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': diff --git a/docs/.vuepress/plugins/examples/stackblitz.js b/docs/.vuepress/plugins/examples/stackblitz.js index c9a004af06..7b891637c8 100644 --- a/docs/.vuepress/plugins/examples/stackblitz.js +++ b/docs/.vuepress/plugins/examples/stackblitz.js @@ -7,7 +7,8 @@ const buildJavascriptBody = ({ id, html, js, css, hyperformulaVersion, lang }) = "version": "1.0.0", "main": "index.html", "dependencies": { - "hyperformula": "${hyperformulaVersion}" + "hyperformula": "${hyperformulaVersion}", + "moment": "latest" } }` }, @@ -56,7 +57,7 @@ const stackblitz = (id, html, js, css, lang) => { ${projects.join('\n')} diff --git a/docs/examples/date-time/example1.css b/docs/examples/date-time/example1.css new file mode 100644 index 0000000000..210cf4dd73 --- /dev/null +++ b/docs/examples/date-time/example1.css @@ -0,0 +1,99 @@ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +.example label { + display: inline-block; + margin-left: 5px; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +.example table { + table-layout: fixed; +} + +.example table tbody tr td, +.example table tbody tr th { + overflow: hidden; + text-overflow: ellipsis; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +.example table tbody tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/docs/examples/date-time/example1.html b/docs/examples/date-time/example1.html new file mode 100644 index 0000000000..4193fe4caa --- /dev/null +++ b/docs/examples/date-time/example1.html @@ -0,0 +1,23 @@ +
+ + + + + + + + + + + + + + + + +
Release 1.0.0Release 4.3.1Number of days between
+
\ No newline at end of file diff --git a/docs/examples/date-time/example1.js b/docs/examples/date-time/example1.js new file mode 100644 index 0000000000..64c13e7b09 --- /dev/null +++ b/docs/examples/date-time/example1.js @@ -0,0 +1,154 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +import moment from 'moment'; + +/* end:skip-in-compilation */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +/** + * Function defining the way HF should handle the provided date string. + * + * @param {string} dateString The date string. + * @param {string} dateFormat The date format. + * @returns {{month: *, year: *, day: *}} Object with date-related information. + */ +const customParseDate = (dateString, dateFormat) => { + const momentDate = moment(dateString, dateFormat, true); + + if (momentDate.isValid()) { + return { + year: momentDate.year(), + month: momentDate.month() + 1, + day: momentDate.date(), + }; + } +}; + +/** + * Date formatting function. + * + * @param {{month: *, year: *, day: *}} dateObject Object with date-related information. + * @returns {string} Formatted date string. + */ +const getFormattedDate = (dateObject) => { + dateObject.month -= 1; + + return moment(dateObject).format('MMM D YY'); +}; + +/** + * Initial table data. + */ +const tableData = [['Jan 31 00', 'Jun 2 01', '=B1-A1']]; +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + parseDateTime: customParseDate, + dateFormats: ['MMM D YY'], + licenseKey: 'gpl-v3', +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet('main'); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId, + }, + tableData +); + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = displayValue(cellAddress, showFormula); + + newTbodyHTML += ` + ${cellValue} + `; + } + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Force the table to display either the formula, the value or a raw source data value. + * + * @param {SimpleCellAddress} cellAddress Cell address. + * @param {boolean} showFormula `true` if the formula should be visible. + */ +function displayValue(cellAddress, showFormula) { + // Declare which columns should display the raw source data, instead of the data from HyperFormula. + let sourceColumns = [0, 1]; + let cellValue = ''; + + if (sourceColumns.includes(cellAddress.col)) { + cellValue = getFormattedDate(hf.numberToDate(hf.getCellValue(cellAddress))); + } else { + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + } + + return cellValue; +} + +/** + * Replace formulas with their results. + */ +function runCalculations() { + renderTable(true); +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector('#run'); + const resetButton = document.querySelector('#reset'); + + runButton.addEventListener('click', () => { + runCalculations(hf, sheetId); + }); + resetButton.addEventListener('click', () => { + resetTable(tableData); + }); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); +// Render the table. +renderTable(); diff --git a/docs/examples/date-time/example1.ts b/docs/examples/date-time/example1.ts new file mode 100644 index 0000000000..8831bcac2e --- /dev/null +++ b/docs/examples/date-time/example1.ts @@ -0,0 +1,154 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +import moment from "moment"; +/* end:skip-in-compilation */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +/** + * Function defining the way HF should handle the provided date string. + * + * @param {string} dateString The date string. + * @param {string} dateFormat The date format. + * @returns {{month: *, year: *, day: *}} Object with date-related information. + */ +const customParseDate = (dateString, dateFormat) => { + const momentDate = moment(dateString, dateFormat, true); + + if (momentDate.isValid()) { + return { + year: momentDate.year(), + month: momentDate.month() + 1, + day: momentDate.date() + }; + } +}; + +/** + * Date formatting function. + * + * @param {{month: *, year: *, day: *}} dateObject Object with date-related information. + * @returns {string} Formatted date string. + */ +const getFormattedDate = dateObject => { + dateObject.month -= 1; + + return moment(dateObject).format("MMM D YY"); +}; + +/** + * Initial table data. + */ +const tableData = [["Jan 31 00", "Jun 2 01", "=B1-A1"]]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + parseDateTime: customParseDate, + dateFormats: ["MMM D YY"], + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData +); + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = displayValue(cellAddress, showFormula); + + newTbodyHTML += ` + ${cellValue} + `; + } + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Force the table to display either the formula, the value or a raw source data value. + * + * @param {SimpleCellAddress} cellAddress Cell address. + * @param {boolean} showFormula `true` if the formula should be visible. + */ +function displayValue(cellAddress, showFormula) { + // Declare which columns should display the raw source data, instead of the data from HyperFormula. + let sourceColumns = [0, 1]; + let cellValue = ""; + + if (sourceColumns.includes(cellAddress.col)) { + cellValue = getFormattedDate(hf.numberToDate(hf.getCellValue(cellAddress))); + } else { + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + } + + return cellValue; +} + +/** + * Replace formulas with their results. + */ +function runCalculations() { + renderTable(true); +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector(".example #run"); + const resetButton = document.querySelector(".example #reset"); + + runButton.addEventListener("click", () => { + runCalculations(hf, sheetId); + }); + + resetButton.addEventListener("click", () => { + resetTable(tableData); + }); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); diff --git a/docs/guide/date-and-time-handling.md b/docs/guide/date-and-time-handling.md index b84ef18890..98ad1fb0cf 100644 --- a/docs/guide/date-and-time-handling.md +++ b/docs/guide/date-and-time-handling.md @@ -98,7 +98,14 @@ And now, HyperFormula recognizes these values as valid dates and can operate on ## Demo - +::: example #example1 --html 1 --css 2 --js 3 --ts 4 + +@[code](@/docs/examples/date-time/example1.html) + +@[code](@/docs/examples/date-time/example1.css) + +@[code](@/docs/examples/date-time/example1.js) + +@[code](@/docs/examples/date-time/example1.ts) + +::: From 56da5352e5857a945d7fdd14e5753f900a2c4ca9 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 3 Oct 2024 18:40:11 +0200 Subject: [PATCH 24/41] Add demo i18n --- docs/.vuepress/config.js | 1 + docs/.vuepress/plugins/examples/examples.js | 4 + docs/examples/date-time/example1.js | 4 +- docs/examples/i18n/example1.css | 102 ++++++++++ docs/examples/i18n/example1.html | 27 +++ docs/examples/i18n/example1.js | 213 ++++++++++++++++++++ docs/examples/i18n/example1.ts | 182 +++++++++++++++++ docs/guide/i18n-features.md | 15 +- 8 files changed, 542 insertions(+), 6 deletions(-) create mode 100644 docs/examples/i18n/example1.css create mode 100644 docs/examples/i18n/example1.html create mode 100644 docs/examples/i18n/example1.js create mode 100644 docs/examples/i18n/example1.ts diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index a7c97643e0..7a4a702c15 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -14,6 +14,7 @@ module.exports = { head: [ // Import HF (required for the examples) [ 'script', { src: 'https://cdn.jsdelivr.net/npm/hyperformula/dist/hyperformula.full.min.js' } ], + [ 'script', { src: 'https://cdn.jsdelivr.net/npm/hyperformula@2.7.1/dist/languages/enUS.js' } ], // Import moment (required for the examples) [ 'script', { src: 'https://cdn.jsdelivr.net/npm/moment/moment.min.js' } ], // Google Tag Manager, an extra element within the `ssr.html` file. diff --git a/docs/.vuepress/plugins/examples/examples.js b/docs/.vuepress/plugins/examples/examples.js index 2bdeb17728..652475345e 100644 --- a/docs/.vuepress/plugins/examples/examples.js +++ b/docs/.vuepress/plugins/examples/examples.js @@ -15,6 +15,8 @@ const parseCode = (content) => { return content // Remove the all "/* start:skip-in-preview */" and "/* end:skip-in-preview */" comments .replace(/\/\*(\s+)?(start|end):skip-in-preview(\s+)?\*\/\n/gm, '') + // Remove the all "/* start:skip-in-sandbox */" and "/* end:skip-in-sandbox */" comments + .replace(/\/\*(\s+)?(start|end):skip-in-sandbox(\s+)?\*\/\n/gm, '') // Remove the code between "/* start:skip-in-compilation */" and "/* end:skip-in-compilation */" expressions .replace(/\/\*(\s+)?start:skip-in-compilation(\s+)?\*\/\n.*?\/\*(\s+)?end:skip-in-compilation(\s+)?\*\/\n/msg, '') // Remove /* end-file */ @@ -25,6 +27,8 @@ const parseCodeSandbox = (content) => { if (!content) return ''; return content + // Remove the code between "/* start:skip-in-sandbox */" and "/* end:skip-in-sandbox */" expressions + .replace(/\/\*(\s+)?start:skip-in-sandbox(\s+)?\*\/\n.*?\/\*(\s+)?end:skip-in-sandbox(\s+)?\*\/\n/msg, '') // Remove the all "/* start:skip-in-preview */" and "/* end:skip-in-preview */" comments .replace(/\/\*(\s+)?(start|end):skip-in-preview(\s+)?\*\/\n/gm, '') // Remove the all "/* start:skip-in-compilation */" and "/* end:skip-in-compilation */" comments diff --git a/docs/examples/date-time/example1.js b/docs/examples/date-time/example1.js index 64c13e7b09..e8db31013e 100644 --- a/docs/examples/date-time/example1.js +++ b/docs/examples/date-time/example1.js @@ -135,8 +135,8 @@ function resetTable() { * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector('#run'); - const resetButton = document.querySelector('#reset'); + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); runButton.addEventListener('click', () => { runCalculations(hf, sheetId); diff --git a/docs/examples/i18n/example1.css b/docs/examples/i18n/example1.css new file mode 100644 index 0000000000..61fd054434 --- /dev/null +++ b/docs/examples/i18n/example1.css @@ -0,0 +1,102 @@ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +.example label { + display: inline-block; + margin-left: 5px; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + +.example table tbody tr:last-child { + font-weight: 600; +} + +.example table tbody tr:last-child td:first-child { + text-align: right; +} + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +.example table { + table-layout: fixed; + font-size: 14px; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +.example table tbody tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/docs/examples/i18n/example1.html b/docs/examples/i18n/example1.html new file mode 100644 index 0000000000..f92527c957 --- /dev/null +++ b/docs/examples/i18n/example1.html @@ -0,0 +1,27 @@ +
+ + + + + + + + + + + + + + + + + + + + +
NameLunch timeDate of BirthAgeSalary
+
\ No newline at end of file diff --git a/docs/examples/i18n/example1.js b/docs/examples/i18n/example1.js new file mode 100644 index 0000000000..b9712e1194 --- /dev/null +++ b/docs/examples/i18n/example1.js @@ -0,0 +1,213 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +import enUS from 'hyperformula/es/i18n/languages/enUS'; +import moment from 'moment'; + +/* end:skip-in-compilation */ +/* start:skip-in-sandbox */ +//const enUS = HyperFormula.languages.enUS; +/* end:skip-in-sandbox */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +/** + * Initial table data. + */ +const tableData = [ + [ + 'Greg Black', + '11:45 AM', + '05/23/1989', + '=YEAR(NOW())-YEAR(C1)', + '$80,000.00', + ], + [ + 'Anne Carpenter', + '12:30 PM', + '01/01/1980', + '=YEAR(NOW())-YEAR(C2)', + '$95,000.00', + ], + [ + 'Natalie Dem', + '1:30 PM', + '12/13/1973', + '=YEAR(NOW())-YEAR(C3)', + '$78,500.00', + ], + [ + 'John Sieg', + '2:00 PM', + '10/31/1995', + '=YEAR(NOW())-YEAR(C4)', + '$114,000.00', + ], + [ + 'Chris Aklips', + '11:30 AM', + '08/18/1987', + '=YEAR(NOW())-YEAR(C5)', + '$71,900.00', + ], + ['AVERAGE', null, null, '=AVERAGE(D1:D5)', '=AVERAGE(E1:E5)'], +]; + +const config = { + language: 'enUS', + dateFormats: ['MM/DD/YYYY', 'MM/DD/YY', 'YYYY/MM/DD'], + timeFormats: ['hh:mm', 'hh:mm:ss.sss'], + decimalSeparator: '.', + thousandSeparator: ',', + functionArgSeparator: ';', + currencySymbol: ['$', 'USD'], + localeLang: 'en-US', + licenseKey: 'gpl-v3', +}; + +HyperFormula.registerLanguage('enUS', enUS); + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty(config); +// Add a new sheet and get its id. +const sheetName = hf.addSheet('main'); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId, + }, + tableData +); + +const columnTypes = ['string', 'time', 'date', 'number', 'currency']; + +/** + * Display value in human-readable format + * + * @param {SimpleCellAddress} cellAddress Cell address. + */ +function formatCellValue(cellAddress) { + if (hf.isCellEmpty(cellAddress)) { + return ''; + } + + if (columnTypes[cellAddress.col] === 'time') { + return formatTime(hf.numberToTime(hf.getCellValue(cellAddress))); + } + + if (columnTypes[cellAddress.col] === 'date') { + return formatDate(hf.numberToDate(hf.getCellValue(cellAddress))); + } + + if (columnTypes[cellAddress.col] === 'currency') { + return formatCurrency(hf.getCellValue(cellAddress)); + } + + return hf.getCellValue(cellAddress); +} + +/** + * Date formatting function. + * + * @param {{month: *, year: *, day: *}} dateObject Object with date-related information. + */ +function formatDate(dateObject) { + dateObject.month -= 1; + + return moment(dateObject).format('MM/DD/YYYY'); +} + +/** + * Time formatting function. + * + * @param dateTimeObject Object with date and time information. + */ +function formatTime(dateTimeObject) { + return moment(dateTimeObject).format('h:mm A'); +} + +/** + * Currency formatting function. + * + * @param value Number representing the currency value + */ +function formatCurrency(value) { + return value.toLocaleString('en-US', { + style: 'currency', + currency: 'USD', + }); +} + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = cellHasFormula && !calculated; + const displayValue = showFormula + ? hf.getCellFormula(cellAddress) + : formatCellValue(cellAddress); + + newTbodyHTML += ` + ${displayValue} + `; + } + + newTbodyHTML += ''; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Replace formulas with their results. + */ +function runCalculations() { + renderTable(true); +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector('#run'); + const resetButton = document.querySelector('#reset'); + + runButton.addEventListener('click', () => { + runCalculations(hf, sheetId); + }); + resetButton.addEventListener('click', () => { + resetTable(tableData); + }); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); +// Render the table. +renderTable(); diff --git a/docs/examples/i18n/example1.ts b/docs/examples/i18n/example1.ts new file mode 100644 index 0000000000..72e127e315 --- /dev/null +++ b/docs/examples/i18n/example1.ts @@ -0,0 +1,182 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +import enUS from "hyperformula/es/i18n/languages/enUS"; +import moment from "moment"; +/* end:skip-in-compilation */ + +/* start:skip-in-sandbox */ +const enUS = HyperFormula.languages.enUS; +/* end:skip-in-sandbox */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +/** + * Initial table data. + */ +const tableData = [ + ["Greg Black", "11:45 AM", "05/23/1989", "=YEAR(NOW())-YEAR(C1)", "$80,000.00"], + ["Anne Carpenter", "12:30 PM", "01/01/1980", "=YEAR(NOW())-YEAR(C2)", "$95,000.00"], + ["Natalie Dem", "1:30 PM", "12/13/1973", "=YEAR(NOW())-YEAR(C3)","$78,500.00"], + ["John Sieg", "2:00 PM", "10/31/1995", "=YEAR(NOW())-YEAR(C4)", "$114,000.00"], + ["Chris Aklips", "11:30 AM", "08/18/1987", "=YEAR(NOW())-YEAR(C5)", "$71,900.00"], + ["AVERAGE", null, null, "=AVERAGE(D1:D5)", "=AVERAGE(E1:E5)"] +]; + +const config = { + language: 'enUS', + dateFormats: ['MM/DD/YYYY', 'MM/DD/YY', 'YYYY/MM/DD'], + timeFormats: ['hh:mm', 'hh:mm:ss.sss'], + decimalSeparator: '.', + thousandSeparator: ',', + functionArgSeparator: ';', + currencySymbol: ['$', 'USD'], + localeLang: 'en-US', + licenseKey: "gpl-v3", +} + +HyperFormula.registerLanguage('enUS', enUS); + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty(config); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData +); + +const columnTypes = ['string', 'time', 'date', 'number', 'currency']; + +/** + * Display value in human-readable format + * + * @param {SimpleCellAddress} cellAddress Cell address. + */ +function formatCellValue(cellAddress) { + if (hf.isCellEmpty(cellAddress)) { + return ""; + } + + if (columnTypes[cellAddress.col] === 'time') { + return formatTime(hf.numberToTime(hf.getCellValue(cellAddress))); + } + + if (columnTypes[cellAddress.col] === 'date') { + return formatDate(hf.numberToDate(hf.getCellValue(cellAddress))); + } + + if (columnTypes[cellAddress.col] === 'currency') { + return formatCurrency((hf.getCellValue(cellAddress))); + } + + return hf.getCellValue(cellAddress) +} + +/** + * Date formatting function. + * + * @param {{month: *, year: *, day: *}} dateObject Object with date-related information. + */ +function formatDate(dateObject) { + dateObject.month -= 1; + + return moment(dateObject).format('MM/DD/YYYY'); +}; + +/** + * Time formatting function. + * + * @param dateTimeObject Object with date and time information. + */ +function formatTime(dateTimeObject) { + return moment(dateTimeObject).format('h:mm A'); +}; + +/** + * Currency formatting function. + * + * @param value Number representing the currency value + */ +function formatCurrency(value) { + return value.toLocaleString('en-US', { + style: 'currency', + currency: 'USD', + }); +}; + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = cellHasFormula && !calculated; + const displayValue = showFormula ? hf.getCellFormula(cellAddress) : formatCellValue(cellAddress); + + newTbodyHTML += ` + ${displayValue} + `; + } + + newTbodyHTML += ""; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Replace formulas with their results. + */ +function runCalculations() { + renderTable(true); +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector(".example #run"); + const resetButton = document.querySelector(".example #reset"); + + runButton.addEventListener("click", () => { + runCalculations(hf, sheetId); + }); + + resetButton.addEventListener("click", () => { + resetTable(tableData); + }); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); diff --git a/docs/guide/i18n-features.md b/docs/guide/i18n-features.md index 1fab319ac4..90eba856c0 100644 --- a/docs/guide/i18n-features.md +++ b/docs/guide/i18n-features.md @@ -105,7 +105,14 @@ localeLang: 'en-US', This demo shows HyperFormula configured for the `en-US` locale. - +::: example #example1 --html 1 --css 2 --js 3 --ts 4 + +@[code](@/docs/examples/i18n/example1.html) + +@[code](@/docs/examples/i18n/example1.css) + +@[code](@/docs/examples/i18n/example1.js) + +@[code](@/docs/examples/i18n/example1.ts) + +::: From 188f074c7ab6a45ab466f202d8248a6d9e9187e5 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Tue, 8 Oct 2024 14:07:05 +0200 Subject: [PATCH 25/41] Add localizing-functions guide --- docs/.vuepress/config.js | 1 + docs/examples/i18n/example1.js | 8 +- .../localizing-functions/example1.css | 103 ++++++++++++ .../localizing-functions/example1.html | 27 +++ .../examples/localizing-functions/example1.js | 149 ++++++++++++++++ .../examples/localizing-functions/example1.ts | 159 ++++++++++++++++++ docs/guide/localizing-functions.md | 15 +- 7 files changed, 454 insertions(+), 8 deletions(-) create mode 100644 docs/examples/localizing-functions/example1.css create mode 100644 docs/examples/localizing-functions/example1.html create mode 100644 docs/examples/localizing-functions/example1.js create mode 100644 docs/examples/localizing-functions/example1.ts diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 7a4a702c15..599773844d 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -15,6 +15,7 @@ module.exports = { // Import HF (required for the examples) [ 'script', { src: 'https://cdn.jsdelivr.net/npm/hyperformula/dist/hyperformula.full.min.js' } ], [ 'script', { src: 'https://cdn.jsdelivr.net/npm/hyperformula@2.7.1/dist/languages/enUS.js' } ], + [ 'script', { src: 'https://cdn.jsdelivr.net/npm/hyperformula@2.7.1/dist/languages/frFR.js' } ], // Import moment (required for the examples) [ 'script', { src: 'https://cdn.jsdelivr.net/npm/moment/moment.min.js' } ], // Google Tag Manager, an extra element within the `ssr.html` file. diff --git a/docs/examples/i18n/example1.js b/docs/examples/i18n/example1.js index b9712e1194..5ad43fa94d 100644 --- a/docs/examples/i18n/example1.js +++ b/docs/examples/i18n/example1.js @@ -1,11 +1,11 @@ /* start:skip-in-compilation */ import HyperFormula from 'hyperformula'; -import enUS from 'hyperformula/es/i18n/languages/enUS'; import moment from 'moment'; /* end:skip-in-compilation */ /* start:skip-in-sandbox */ -//const enUS = HyperFormula.languages.enUS; +const enUS = HyperFormula.languages.enUS; + /* end:skip-in-sandbox */ console.log( `%c Using HyperFormula ${HyperFormula.version}`, @@ -194,8 +194,8 @@ function resetTable() { * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector('#run'); - const resetButton = document.querySelector('#reset'); + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); runButton.addEventListener('click', () => { runCalculations(hf, sheetId); diff --git a/docs/examples/localizing-functions/example1.css b/docs/examples/localizing-functions/example1.css new file mode 100644 index 0000000000..f72f0ce758 --- /dev/null +++ b/docs/examples/localizing-functions/example1.css @@ -0,0 +1,103 @@ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +.example label { + display: inline-block; + margin-left: 5px; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + +.example table tbody tr:last-child { + font-weight: 600; +} + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +.example table { + table-layout: fixed; +} + +.example table tbody tr td, +.example table tbody tr th { + overflow: hidden; + text-overflow: ellipsis; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +.example table tbody tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/docs/examples/localizing-functions/example1.html b/docs/examples/localizing-functions/example1.html new file mode 100644 index 0000000000..c5c58267f2 --- /dev/null +++ b/docs/examples/localizing-functions/example1.html @@ -0,0 +1,27 @@ +
+ + + + + + + + + + + + + + + + + + + + +
NameYear_1Year_2AverageSum
+
\ No newline at end of file diff --git a/docs/examples/localizing-functions/example1.js b/docs/examples/localizing-functions/example1.js new file mode 100644 index 0000000000..3aa26bedb8 --- /dev/null +++ b/docs/examples/localizing-functions/example1.js @@ -0,0 +1,149 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; + +/* end:skip-in-compilation */ +/* start:skip-in-sandbox */ +const frFR = HyperFormula.languages.frFR; + +/* end:skip-in-sandbox */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +/** + * Initial table data. + */ +const tableData = [ + ['Greg Black', 4.66, '=B1*1.3', '=MOYENNE(B1:C1)', '=SOMME(B1:C1)'], + ['Anne Carpenter', 5.25, '=$B$2*30%', '=MOYENNE(B2:C2)', '=SOMME(B2:C2)'], + ['Natalie Dem', 3.59, '=B3*2.7+2+1', '=MOYENNE(B3:C3)', '=SOMME(B3:C3)'], + ['John Sieg', 12.51, '=B4*(1.22+1)', '=MOYENNE(B4:C4)', '=SOMME(B4:C4)'], + [ + 'Chris Aklips', + 7.63, + '=B5*1.1*SUM(10,20)+1', + '=MOYENNE(B5:C5)', + '=SOMME(B5:C5)', + ], +]; + +// register language +HyperFormula.registerLanguage('frFR', frFR); + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + language: 'frFR', + licenseKey: 'gpl-v3', +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet('main'); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId, + }, + tableData +); +// Add named expressions for the "TOTAL" row. +hf.addNamedExpression('Year_1', '=SOMME(main!$B$1:main!$B$5)'); +hf.addNamedExpression('Year_2', '=SOMME(main!$C$1:main!$C$5)'); + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const totals = ['=SOMME(Year_1)', '=SOMME(Year_2)']; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + let totalRowsHTML = ''; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = ''; + + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + + if (!isNaN(cellValue)) { + cellValue = cellValue.toFixed(2); + } + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ''; + } + + totalRowsHTML = ` +TOTAL + + ${ + calculated ? hf.calculateFormula(totals[0], sheetId).toFixed(2) : totals[0] + } + + + ${ + calculated ? hf.calculateFormula(totals[1], sheetId).toFixed(2) : totals[1] + } + + +`; + newTbodyHTML += totalRowsHTML; + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Replace formulas with their results. + */ +function runCalculations() { + renderTable(true); +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); + + runButton.addEventListener('click', () => { + runCalculations(hf, sheetId); + }); + resetButton.addEventListener('click', () => { + resetTable(tableData); + }); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); +// Render the table. +renderTable(); diff --git a/docs/examples/localizing-functions/example1.ts b/docs/examples/localizing-functions/example1.ts new file mode 100644 index 0000000000..0b2731d80a --- /dev/null +++ b/docs/examples/localizing-functions/example1.ts @@ -0,0 +1,159 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +import frFR from "hyperformula/es/i18n/languages/frFR"; +/* end:skip-in-compilation */ + +/* start:skip-in-sandbox */ +const frFR = HyperFormula.languages.frFR; +/* end:skip-in-sandbox */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +/** + * Initial table data. + */ +const tableData = [ + ["Greg Black", 4.66, "=B1*1.3", "=MOYENNE(B1:C1)", "=SOMME(B1:C1)"], + ["Anne Carpenter", 5.25, "=$B$2*30%", "=MOYENNE(B2:C2)", "=SOMME(B2:C2)"], + ["Natalie Dem", 3.59, "=B3*2.7+2+1", "=MOYENNE(B3:C3)", "=SOMME(B3:C3)"], + ["John Sieg", 12.51, "=B4*(1.22+1)", "=MOYENNE(B4:C4)", "=SOMME(B4:C4)"], + [ + "Chris Aklips", + 7.63, + "=B5*1.1*SUM(10,20)+1", + "=MOYENNE(B5:C5)", + "=SOMME(B5:C5)" + ] +]; + +// register language +HyperFormula.registerLanguage( + "frFR", + frFR +); + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + language: "frFR", + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData +); + +// Add named expressions for the "TOTAL" row. +hf.addNamedExpression("Year_1", "=SOMME(main!$B$1:main!$B$5)"); +hf.addNamedExpression("Year_2", "=SOMME(main!$C$1:main!$C$5)"); + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const totals = ["=SOMME(Year_1)", "=SOMME(Year_2)"]; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + let totalRowsHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = ""; + + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + + if (!isNaN(cellValue)) { + cellValue = cellValue.toFixed(2); + } + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ""; + } + + totalRowsHTML = ` +TOTAL + + ${ + calculated + ? hf.calculateFormula(totals[0], sheetId).toFixed(2) + : totals[0] + } + + + ${ + calculated + ? hf.calculateFormula(totals[1], sheetId).toFixed(2) + : totals[1] + } + + +`; + + newTbodyHTML += totalRowsHTML; + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Replace formulas with their results. + */ +function runCalculations() { + renderTable(true); +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector(".example #run"); + const resetButton = document.querySelector(".example #reset"); + + runButton.addEventListener("click", () => { + runCalculations(hf, sheetId); + }); + + resetButton.addEventListener("click", () => { + resetTable(tableData); + }); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); diff --git a/docs/guide/localizing-functions.md b/docs/guide/localizing-functions.md index fdf5946f02..4622b6c9c5 100644 --- a/docs/guide/localizing-functions.md +++ b/docs/guide/localizing-functions.md @@ -96,7 +96,14 @@ You can localize your custom functions as well. For details, see the [Custom fun ## Demo - +::: example #example1 --html 1 --css 2 --js 3 --ts 4 + +@[code](@/docs/examples/localizing-functions/example1.html) + +@[code](@/docs/examples/localizing-functions/example1.css) + +@[code](@/docs/examples/localizing-functions/example1.js) + +@[code](@/docs/examples/localizing-functions/example1.ts) + +::: From dfad1b089a402911c254922eb7d9582212ec0012 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Tue, 8 Oct 2024 14:15:58 +0200 Subject: [PATCH 26/41] Add named-expressions demo --- docs/examples/named-expressions/example1.css | 105 +++++++++++++++ docs/examples/named-expressions/example1.html | 19 +++ docs/examples/named-expressions/example1.js | 121 +++++++++++++++++ docs/examples/named-expressions/example1.ts | 122 ++++++++++++++++++ docs/guide/named-expressions.md | 15 ++- 5 files changed, 378 insertions(+), 4 deletions(-) create mode 100644 docs/examples/named-expressions/example1.css create mode 100644 docs/examples/named-expressions/example1.html create mode 100644 docs/examples/named-expressions/example1.js create mode 100644 docs/examples/named-expressions/example1.ts diff --git a/docs/examples/named-expressions/example1.css b/docs/examples/named-expressions/example1.css new file mode 100644 index 0000000000..4960e9d283 --- /dev/null +++ b/docs/examples/named-expressions/example1.css @@ -0,0 +1,105 @@ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +.example label { + display: inline-block; + margin-left: 5px; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + +.example table tbody tr:nth-child(4), +.example table tbody tr:nth-child(5) { + font-weight: 600; +} + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +.example table { + table-layout: fixed; +} + +.example table tbody tr td, +.example table tbody tr th { + overflow: hidden; + text-overflow: ellipsis; + word-break: break-all; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +.example table tbody tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/docs/examples/named-expressions/example1.html b/docs/examples/named-expressions/example1.html new file mode 100644 index 0000000000..a276542d8b --- /dev/null +++ b/docs/examples/named-expressions/example1.html @@ -0,0 +1,19 @@ +
+ + + + + + + + + + + + +
ABCD
+
diff --git a/docs/examples/named-expressions/example1.js b/docs/examples/named-expressions/example1.js new file mode 100644 index 0000000000..c737293f9d --- /dev/null +++ b/docs/examples/named-expressions/example1.js @@ -0,0 +1,121 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; + +/* end:skip-in-compilation */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +/** + * Initial table data. + */ +const tableData = [ + [10, 20, 20, 30], + [50, 60, 70, 80], + [90, 100, 110, 120], + ['=myOneCell', '=myTwoCells', '=myOneColumn', '=myTwoColumns'], + ['=myFormula+myNumber+34', '=myText', '=myOneRow', '=myTwoRows'], +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: 'gpl-v3', +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet('main'); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId, + }, + tableData +); +// Add named expressions +hf.addNamedExpression('myOneCell', '=main!$A$1'); +hf.addNamedExpression('myTwoCells', '=SUM(main!$A$1, main!$A$2)'); +hf.addNamedExpression('myOneColumn', '=SUM(main!$A$1:main!$A$3)'); +hf.addNamedExpression('myTwoColumns', '=SUM(main!$A$1:main!$B$3)'); +hf.addNamedExpression('myOneRow', '=SUM(main!$A$1:main!$D$1)'); +hf.addNamedExpression('myTwoRows', '=SUM(main!$A$1:main!$D$2)'); +hf.addNamedExpression('myFormula', '=SUM(0, 1, 1, 2, 3, 5, 8, 13)'); +hf.addNamedExpression('myNumber', '=21'); +hf.addNamedExpression('myText', 'Apollo 11'); + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = ''; + + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ''; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Replace formulas with their results. + */ +function runCalculations() { + renderTable(true); +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); + + runButton.addEventListener('click', () => { + runCalculations(hf, sheetId); + }); + resetButton.addEventListener('click', () => { + resetTable(tableData); + }); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); +// Render the table. +renderTable(); diff --git a/docs/examples/named-expressions/example1.ts b/docs/examples/named-expressions/example1.ts new file mode 100644 index 0000000000..83d34b801e --- /dev/null +++ b/docs/examples/named-expressions/example1.ts @@ -0,0 +1,122 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +/* end:skip-in-compilation */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +/** + * Initial table data. + */ +const tableData = [ + [10, 20, 20, 30], + [50, 60, 70, 80], + [90, 100, 110, 120], + ["=myOneCell", "=myTwoCells", "=myOneColumn", "=myTwoColumns"], + ["=myFormula+myNumber+34", "=myText", "=myOneRow", "=myTwoRows"] +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData +); + +// Add named expressions +hf.addNamedExpression("myOneCell", "=main!$A$1"); +hf.addNamedExpression("myTwoCells", "=SUM(main!$A$1, main!$A$2)"); +hf.addNamedExpression("myOneColumn", "=SUM(main!$A$1:main!$A$3)"); +hf.addNamedExpression("myTwoColumns", "=SUM(main!$A$1:main!$B$3)"); +hf.addNamedExpression("myOneRow", "=SUM(main!$A$1:main!$D$1)"); +hf.addNamedExpression("myTwoRows", "=SUM(main!$A$1:main!$D$2)"); +hf.addNamedExpression("myFormula", "=SUM(0, 1, 1, 2, 3, 5, 8, 13)"); +hf.addNamedExpression("myNumber", "=21"); +hf.addNamedExpression("myText", "Apollo 11"); + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = ""; + + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ""; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Replace formulas with their results. + */ +function runCalculations() { + renderTable(true); +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const runButton = document.querySelector(".example #run"); + const resetButton = document.querySelector(".example #reset"); + + runButton.addEventListener("click", () => { + runCalculations(hf, sheetId); + }); + + resetButton.addEventListener("click", () => { + resetTable(tableData); + }); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); diff --git a/docs/guide/named-expressions.md b/docs/guide/named-expressions.md index 8284ecff66..9c34c196cc 100644 --- a/docs/guide/named-expressions.md +++ b/docs/guide/named-expressions.md @@ -149,7 +149,14 @@ described in [that section](basic-operations.md#isitpossibleto-methods). ## Demo - +::: example #example1 --html 1 --css 2 --js 3 --ts 4 + +@[code](@/docs/examples/named-expressions/example1.html) + +@[code](@/docs/examples/named-expressions/example1.css) + +@[code](@/docs/examples/named-expressions/example1.js) + +@[code](@/docs/examples/named-expressions/example1.ts) + +::: From 41d1ae7da87ce8e7535975fcc246aa21c9012275 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Tue, 8 Oct 2024 14:25:08 +0200 Subject: [PATCH 27/41] Add sorting-data demo --- docs/examples/sorting-data/example1.css | 100 +++++++++++++++ docs/examples/sorting-data/example1.html | 18 +++ docs/examples/sorting-data/example1.js | 155 ++++++++++++++++++++++ docs/examples/sorting-data/example1.ts | 157 +++++++++++++++++++++++ docs/guide/sorting-data.md | 15 ++- 5 files changed, 441 insertions(+), 4 deletions(-) create mode 100644 docs/examples/sorting-data/example1.css create mode 100644 docs/examples/sorting-data/example1.html create mode 100644 docs/examples/sorting-data/example1.js create mode 100644 docs/examples/sorting-data/example1.ts diff --git a/docs/examples/sorting-data/example1.css b/docs/examples/sorting-data/example1.css new file mode 100644 index 0000000000..894f36f33e --- /dev/null +++ b/docs/examples/sorting-data/example1.css @@ -0,0 +1,100 @@ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +.example label { + display: inline-block; + margin-left: 5px; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +.example table { + table-layout: fixed; +} + +.example table tbody tr td, +.example table tbody tr th { + overflow: hidden; + text-overflow: ellipsis; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +.example table tbody tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/docs/examples/sorting-data/example1.html b/docs/examples/sorting-data/example1.html new file mode 100644 index 0000000000..be037f8baf --- /dev/null +++ b/docs/examples/sorting-data/example1.html @@ -0,0 +1,18 @@ +
+ + + + + + + + + + + + +
Name + Score + +
+
diff --git a/docs/examples/sorting-data/example1.js b/docs/examples/sorting-data/example1.js new file mode 100644 index 0000000000..af643b6b17 --- /dev/null +++ b/docs/examples/sorting-data/example1.js @@ -0,0 +1,155 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; + +/* end:skip-in-compilation */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +/** + * Initial table data. + */ +const tableData = [ + ['Greg Black', '100'], + ['Anne Carpenter', '=SUM(100,100)'], + ['Natalie Dem', '500'], + ['John Sieg', '50'], + ['Chris Aklips', '20'], + ['Bart Hoopoe', '700'], + ['Chris Site', '80'], + ['Agnes Whitey', '90'], +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: 'gpl-v3', +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet('main'); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId, + }, + tableData +); + +/** + * Sort the HF's dataset. + * + * @param {boolean} ascending `true` if sorting in ascending order, `false` otherwise. + * @param {Function} callback The callback function. + */ +function sort(ascending, callback) { + const rowCount = hf.getSheetDimensions(sheetId).height; + const colValues = []; + let newOrder = null; + let newOrderMapping = []; + + for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) { + colValues.push({ + rowIndex, + value: hf.getCellValue({ + sheet: sheetId, + col: 1, + row: rowIndex, + }), + }); + } + + colValues.sort((objA, objB) => { + const delta = objA.value - objB.value; + + return ascending ? delta : -delta; + }); + newOrder = colValues.map((el) => el.rowIndex); + newOrder.forEach((orderIndex, arrIndex) => { + newOrderMapping[orderIndex] = arrIndex; + }); + hf.setRowOrder(sheetId, newOrderMapping); + callback(); +} + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = ''; + + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ''; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +const doSortASC = () => { + sort(true, () => { + renderTable(true); + }); +}; + +const doSortDESC = () => { + sort(false, () => { + renderTable(true); + }); +}; + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const ascSort = document.querySelector('#asc'); + const descSort = document.querySelector('#desc'); + + ascSort.addEventListener('click', () => { + doSortASC(); + }); + descSort.addEventListener('click', () => { + doSortDESC(); + }); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); +// Render the table. +renderTable(); diff --git a/docs/examples/sorting-data/example1.ts b/docs/examples/sorting-data/example1.ts new file mode 100644 index 0000000000..d2449b4875 --- /dev/null +++ b/docs/examples/sorting-data/example1.ts @@ -0,0 +1,157 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +/* end:skip-in-compilation */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +/** + * Initial table data. + */ +const tableData = [ + ["Greg Black", "100"], + ["Anne Carpenter", "=SUM(100,100)"], + ["Natalie Dem", "500"], + ["John Sieg", "50"], + ["Chris Aklips", "20"], + ["Bart Hoopoe", "700"], + ["Chris Site", "80"], + ["Agnes Whitey", "90"] +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData +); + +/** + * Sort the HF's dataset. + * + * @param {boolean} ascending `true` if sorting in ascending order, `false` otherwise. + * @param {Function} callback The callback function. + */ +function sort(ascending, callback) { + const rowCount = hf.getSheetDimensions(sheetId).height; + const colValues = []; + let newOrder = null; + let newOrderMapping = []; + + for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) { + colValues.push({ + rowIndex, + value: hf.getCellValue({ + sheet: sheetId, + col: 1, + row: rowIndex + }) + }); + } + + colValues.sort((objA, objB) => { + const delta = objA.value - objB.value; + return ascending ? delta : -delta; + }); + + newOrder = colValues.map((el) => el.rowIndex); + + newOrder.forEach((orderIndex, arrIndex) => { + newOrderMapping[orderIndex] = arrIndex; + }); + + hf.setRowOrder(sheetId, newOrderMapping); + + callback(); +} + +/** + * Fill the HTML table with data. + * + * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. + */ +function renderTable(calculated = false) { + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + const cellHasFormula = hf.doesCellHaveFormula(cellAddress); + const showFormula = calculated || !cellHasFormula; + let cellValue = ""; + + if (!hf.isCellEmpty(cellAddress) && showFormula) { + cellValue = hf.getCellValue(cellAddress); + } else { + cellValue = hf.getCellFormula(cellAddress); + } + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ""; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Replace the values in the table with initial data. + */ +function resetTable() { + renderTable(); +} + +const doSortASC = () => { + sort(true, () => { + renderTable(true); + }); +}; + +const doSortDESC = () => { + sort(false, () => { + renderTable(true); + }); +}; + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const ascSort = document.querySelector("#asc"); + const descSort = document.querySelector("#desc"); + + ascSort.addEventListener("click", () => { + doSortASC(); + }); + + descSort.addEventListener("click", () => { + doSortDESC(); + }); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); diff --git a/docs/guide/sorting-data.md b/docs/guide/sorting-data.md index 1eaaa1dc0d..8faedd3ca9 100644 --- a/docs/guide/sorting-data.md +++ b/docs/guide/sorting-data.md @@ -195,7 +195,14 @@ if (!isColumnOrderOk) { The demo below shows how to sort rows in ascending and descending order, based on the results (calculated values) of the cells in the second column. - +::: example #example1 --html 1 --css 2 --js 3 --ts 4 + +@[code](@/docs/examples/sorting-data/example1.html) + +@[code](@/docs/examples/sorting-data/example1.css) + +@[code](@/docs/examples/sorting-data/example1.js) + +@[code](@/docs/examples/sorting-data/example1.ts) + +::: From 83b7b8532022abbe8faf095ef3ad8aac82292216 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Tue, 8 Oct 2024 16:51:12 +0200 Subject: [PATCH 28/41] Add undo-redo demo --- docs/examples/sorting-data/example1.js | 4 +- docs/examples/sorting-data/example1.ts | 4 +- docs/examples/undo-redo/example1.css | 98 ++++++++++++++++++ docs/examples/undo-redo/example1.html | 22 ++++ docs/examples/undo-redo/example1.js | 138 +++++++++++++++++++++++++ docs/examples/undo-redo/example1.ts | 135 ++++++++++++++++++++++++ docs/guide/undo-redo.md | 15 ++- 7 files changed, 408 insertions(+), 8 deletions(-) create mode 100644 docs/examples/undo-redo/example1.css create mode 100644 docs/examples/undo-redo/example1.html create mode 100644 docs/examples/undo-redo/example1.js create mode 100644 docs/examples/undo-redo/example1.ts diff --git a/docs/examples/sorting-data/example1.js b/docs/examples/sorting-data/example1.js index af643b6b17..9c91575d5c 100644 --- a/docs/examples/sorting-data/example1.js +++ b/docs/examples/sorting-data/example1.js @@ -136,8 +136,8 @@ const doSortDESC = () => { * Bind the events to the buttons. */ function bindEvents() { - const ascSort = document.querySelector('#asc'); - const descSort = document.querySelector('#desc'); + const ascSort = document.querySelector('.example #asc'); + const descSort = document.querySelector('.example #desc'); ascSort.addEventListener('click', () => { doSortASC(); diff --git a/docs/examples/sorting-data/example1.ts b/docs/examples/sorting-data/example1.ts index d2449b4875..f300435d32 100644 --- a/docs/examples/sorting-data/example1.ts +++ b/docs/examples/sorting-data/example1.ts @@ -136,8 +136,8 @@ const doSortDESC = () => { * Bind the events to the buttons. */ function bindEvents() { - const ascSort = document.querySelector("#asc"); - const descSort = document.querySelector("#desc"); + const ascSort = document.querySelector(".example #asc"); + const descSort = document.querySelector(".example #desc"); ascSort.addEventListener("click", () => { doSortASC(); diff --git a/docs/examples/undo-redo/example1.css b/docs/examples/undo-redo/example1.css new file mode 100644 index 0000000000..4b5baea84c --- /dev/null +++ b/docs/examples/undo-redo/example1.css @@ -0,0 +1,98 @@ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +.example label { + display: inline-block; + margin-left: 5px; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +.example table { + table-layout: fixed; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +.example table tbody tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + +.example #info-box { + font-size: 1.5rem; + margin-bottom: 10px; +} + +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/docs/examples/undo-redo/example1.html b/docs/examples/undo-redo/example1.html new file mode 100644 index 0000000000..3451ac6cb1 --- /dev/null +++ b/docs/examples/undo-redo/example1.html @@ -0,0 +1,22 @@ +
+ + +

 

+ + + + + + + + + + + + +
NameValue
+
\ No newline at end of file diff --git a/docs/examples/undo-redo/example1.js b/docs/examples/undo-redo/example1.js new file mode 100644 index 0000000000..a5894deeff --- /dev/null +++ b/docs/examples/undo-redo/example1.js @@ -0,0 +1,138 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; + +/* end:skip-in-compilation */ +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); + +/** + * Initial table data. + */ +const tableData = [ + ['Greg', '2'], + ['Chris', '4'], +]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: 'gpl-v3', +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet('main'); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId, + }, + tableData +); +// Clear the undo stack to prevent undoing the initialization steps. +hf.clearUndoStack(); + +/** + * Fill the HTML table with data. + */ +function renderTable() { + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + let cellValue = hf.getCellValue(cellAddress); + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ''; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Clear the existing information. + */ +function clearInfo() { + const infoBoxDOM = document.querySelector('.example #info-box'); + + infoBoxDOM.innerHTML = ' '; +} + +/** + * Display the provided message in the info box. + * + * @param {string} message Message to display. + */ +function displayInfo(message) { + const infoBoxDOM = document.querySelector('.example #info-box'); + + infoBoxDOM.innerText = message; +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const removeRowButton = document.querySelector('.example #remove-row'); + const undoButton = document.querySelector('.example #undo'); + + removeRowButton.addEventListener('click', () => { + removeSecondRow(); + }); + undoButton.addEventListener('click', () => { + undo(); + }); +} + +/** + * Remove the second row from the table. + */ +function removeSecondRow() { + const filledRowCount = hf.getSheetDimensions(sheetId).height; + + clearInfo(); + + if (filledRowCount < 2) { + displayInfo("There's not enough filled rows to perform this action."); + + return; + } + + hf.removeRows(sheetId, [1, 1]); + renderTable(true); +} + +/** + * Run the HF undo action. + */ +function undo() { + clearInfo(); + + if (!hf.isThereSomethingToUndo()) { + displayInfo("There's nothing to undo."); + + return; + } + + hf.undo(); + renderTable(); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); +// Render the table. +renderTable(); diff --git a/docs/examples/undo-redo/example1.ts b/docs/examples/undo-redo/example1.ts new file mode 100644 index 0000000000..5761d56a04 --- /dev/null +++ b/docs/examples/undo-redo/example1.ts @@ -0,0 +1,135 @@ +/* start:skip-in-compilation */ +import HyperFormula from 'hyperformula'; +/* end:skip-in-compilation */ + +console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); + +/** + * Initial table data. + */ +const tableData = [["Greg", "2"], ["Chris", "4"]]; + +// Create an empty HyperFormula instance. +const hf = HyperFormula.buildEmpty({ + licenseKey: "gpl-v3" +}); + +// Add a new sheet and get its id. +const sheetName = hf.addSheet("main"); +const sheetId = hf.getSheetId(sheetName); + +// Fill the HyperFormula sheet with data. +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId + }, + tableData +); + +// Clear the undo stack to prevent undoing the initialization steps. +hf.clearUndoStack(); + +/** + * Fill the HTML table with data. + */ +function renderTable() { + const tbodyDOM = document.querySelector(".example tbody"); + const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ""; + + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + const cellAddress = { sheet: sheetId, col, row }; + let cellValue = hf.getCellValue(cellAddress); + + newTbodyHTML += ` + ${cellValue} + `; + } + + newTbodyHTML += ""; + } + + tbodyDOM.innerHTML = newTbodyHTML; +} + +/** + * Clear the existing information. + */ +function clearInfo() { + const infoBoxDOM = document.querySelector(".example #info-box"); + + infoBoxDOM.innerHTML = " "; +} + +/** + * Display the provided message in the info box. + * + * @param {string} message Message to display. + */ +function displayInfo(message) { + const infoBoxDOM = document.querySelector(".example #info-box"); + + infoBoxDOM.innerText = message; +} + +/** + * Bind the events to the buttons. + */ +function bindEvents() { + const removeRowButton = document.querySelector(".example #remove-row"); + const undoButton = document.querySelector(".example #undo"); + + removeRowButton.addEventListener("click", () => { + removeSecondRow(); + }); + + undoButton.addEventListener("click", () => { + undo(); + }); +} + +/** + * Remove the second row from the table. + */ +function removeSecondRow() { + const filledRowCount = hf.getSheetDimensions(sheetId).height; + + clearInfo(); + + if (filledRowCount < 2) { + displayInfo("There's not enough filled rows to perform this action."); + + return; + } + + hf.removeRows(sheetId, [1, 1]); + renderTable(true); +} + +/** + * Run the HF undo action. + */ +function undo() { + clearInfo(); + + if (!hf.isThereSomethingToUndo()) { + displayInfo("There's nothing to undo."); + + return; + } + + hf.undo(); + renderTable(); +} + +const ANIMATION_ENABLED = true; + +// Bind the button events. +bindEvents(); + +// Render the table. +renderTable(); diff --git a/docs/guide/undo-redo.md b/docs/guide/undo-redo.md index c34b5f8849..dceb482025 100644 --- a/docs/guide/undo-redo.md +++ b/docs/guide/undo-redo.md @@ -25,7 +25,14 @@ that undo-redo will recognize them as a single cumulative operation. ## Demo - +::: example #example1 --html 1 --css 2 --js 3 --ts 4 + +@[code](@/docs/examples/undo-redo/example1.html) + +@[code](@/docs/examples/undo-redo/example1.css) + +@[code](@/docs/examples/undo-redo/example1.js) + +@[code](@/docs/examples/undo-redo/example1.ts) + +::: From 95a1550b507c585c46a887995176421bc12cd6ff Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Wed, 9 Oct 2024 09:19:19 +0200 Subject: [PATCH 29/41] Fix lint errors --- docs/examples/advanced-usage/example1.js | 2 +- docs/examples/advanced-usage/example1.ts | 2 +- docs/examples/basic-operations/example1.js | 4 +--- docs/examples/basic-operations/example1.ts | 4 +--- docs/examples/date-time/example1.js | 4 ++-- docs/examples/date-time/example1.ts | 4 ++-- docs/examples/i18n/example1.js | 4 ++-- docs/examples/i18n/example1.ts | 6 +++--- docs/examples/localizing-functions/example1.js | 4 ++-- docs/examples/localizing-functions/example1.ts | 4 ++-- docs/examples/named-expressions/example1.js | 4 ++-- docs/examples/named-expressions/example1.ts | 4 ++-- docs/examples/sorting-data/example1.js | 7 ------- docs/examples/sorting-data/example1.ts | 7 ------- docs/examples/undo-redo/example1.js | 2 +- docs/examples/undo-redo/example1.ts | 2 +- 16 files changed, 23 insertions(+), 41 deletions(-) diff --git a/docs/examples/advanced-usage/example1.js b/docs/examples/advanced-usage/example1.js index 375e38d719..a02c7d20e8 100644 --- a/docs/examples/advanced-usage/example1.js +++ b/docs/examples/advanced-usage/example1.js @@ -124,6 +124,6 @@ function bindEvents() { bindEvents(); // Render the preview tables. -for (const [tableName, tableInfo] of Object.entries(sheetInfo)) { +for (const [_, tableInfo] of Object.entries(sheetInfo)) { renderTable(tableInfo.sheetName); } diff --git a/docs/examples/advanced-usage/example1.ts b/docs/examples/advanced-usage/example1.ts index beb01e07c4..f58bd729ef 100644 --- a/docs/examples/advanced-usage/example1.ts +++ b/docs/examples/advanced-usage/example1.ts @@ -119,6 +119,6 @@ function bindEvents() { bindEvents(); // Render the preview tables. -for (const [tableName, tableInfo] of Object.entries(sheetInfo)) { +for (const [_, tableInfo] of Object.entries(sheetInfo)) { renderTable(tableInfo.sheetName); } diff --git a/docs/examples/basic-operations/example1.js b/docs/examples/basic-operations/example1.js index f0630133cc..17ccaf8efe 100644 --- a/docs/examples/basic-operations/example1.js +++ b/docs/examples/basic-operations/example1.js @@ -164,10 +164,8 @@ hf.setSheetContent(sheetId, getSampleData(5, 5)); /** * Fill the HTML table with data. - * - * @param {string} sheetName Sheet name. */ -function renderTable(sheetName) { +function renderTable() { const sheetId = hf.getSheetId(state.currentSheet); const tbodyDOM = document.querySelector('.example tbody'); const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; diff --git a/docs/examples/basic-operations/example1.ts b/docs/examples/basic-operations/example1.ts index 27d4188bcd..8178f2e53a 100644 --- a/docs/examples/basic-operations/example1.ts +++ b/docs/examples/basic-operations/example1.ts @@ -160,10 +160,8 @@ hf.setSheetContent(sheetId, getSampleData(5, 5)); /** * Fill the HTML table with data. - * - * @param {string} sheetName Sheet name. */ -function renderTable(sheetName) { +function renderTable() { const sheetId = hf.getSheetId(state.currentSheet); const tbodyDOM = document.querySelector(".example tbody"); const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; diff --git a/docs/examples/date-time/example1.js b/docs/examples/date-time/example1.js index e8db31013e..71ca4b278e 100644 --- a/docs/examples/date-time/example1.js +++ b/docs/examples/date-time/example1.js @@ -139,10 +139,10 @@ function bindEvents() { const resetButton = document.querySelector('.example #reset'); runButton.addEventListener('click', () => { - runCalculations(hf, sheetId); + runCalculations(); }); resetButton.addEventListener('click', () => { - resetTable(tableData); + resetTable(); }); } diff --git a/docs/examples/date-time/example1.ts b/docs/examples/date-time/example1.ts index 8831bcac2e..b144bacab9 100644 --- a/docs/examples/date-time/example1.ts +++ b/docs/examples/date-time/example1.ts @@ -137,11 +137,11 @@ function bindEvents() { const resetButton = document.querySelector(".example #reset"); runButton.addEventListener("click", () => { - runCalculations(hf, sheetId); + runCalculations(); }); resetButton.addEventListener("click", () => { - resetTable(tableData); + resetTable(); }); } diff --git a/docs/examples/i18n/example1.js b/docs/examples/i18n/example1.js index 5ad43fa94d..89f7d266d2 100644 --- a/docs/examples/i18n/example1.js +++ b/docs/examples/i18n/example1.js @@ -198,10 +198,10 @@ function bindEvents() { const resetButton = document.querySelector('.example #reset'); runButton.addEventListener('click', () => { - runCalculations(hf, sheetId); + runCalculations(); }); resetButton.addEventListener('click', () => { - resetTable(tableData); + resetTable(); }); } diff --git a/docs/examples/i18n/example1.ts b/docs/examples/i18n/example1.ts index 72e127e315..564983f62e 100644 --- a/docs/examples/i18n/example1.ts +++ b/docs/examples/i18n/example1.ts @@ -32,7 +32,7 @@ const config = { currencySymbol: ['$', 'USD'], localeLang: 'en-US', licenseKey: "gpl-v3", -} +}; HyperFormula.registerLanguage('enUS', enUS); @@ -165,11 +165,11 @@ function bindEvents() { const resetButton = document.querySelector(".example #reset"); runButton.addEventListener("click", () => { - runCalculations(hf, sheetId); + runCalculations(); }); resetButton.addEventListener("click", () => { - resetTable(tableData); + resetTable(); }); } diff --git a/docs/examples/localizing-functions/example1.js b/docs/examples/localizing-functions/example1.js index 3aa26bedb8..1bf70fa0ef 100644 --- a/docs/examples/localizing-functions/example1.js +++ b/docs/examples/localizing-functions/example1.js @@ -134,10 +134,10 @@ function bindEvents() { const resetButton = document.querySelector('.example #reset'); runButton.addEventListener('click', () => { - runCalculations(hf, sheetId); + runCalculations(); }); resetButton.addEventListener('click', () => { - resetTable(tableData); + resetTable(); }); } diff --git a/docs/examples/localizing-functions/example1.ts b/docs/examples/localizing-functions/example1.ts index 0b2731d80a..68e9a365f1 100644 --- a/docs/examples/localizing-functions/example1.ts +++ b/docs/examples/localizing-functions/example1.ts @@ -142,11 +142,11 @@ function bindEvents() { const resetButton = document.querySelector(".example #reset"); runButton.addEventListener("click", () => { - runCalculations(hf, sheetId); + runCalculations(); }); resetButton.addEventListener("click", () => { - resetTable(tableData); + resetTable(); }); } diff --git a/docs/examples/named-expressions/example1.js b/docs/examples/named-expressions/example1.js index c737293f9d..2e94802559 100644 --- a/docs/examples/named-expressions/example1.js +++ b/docs/examples/named-expressions/example1.js @@ -106,10 +106,10 @@ function bindEvents() { const resetButton = document.querySelector('.example #reset'); runButton.addEventListener('click', () => { - runCalculations(hf, sheetId); + runCalculations(); }); resetButton.addEventListener('click', () => { - resetTable(tableData); + resetTable(); }); } diff --git a/docs/examples/named-expressions/example1.ts b/docs/examples/named-expressions/example1.ts index 83d34b801e..19bfabead5 100644 --- a/docs/examples/named-expressions/example1.ts +++ b/docs/examples/named-expressions/example1.ts @@ -105,11 +105,11 @@ function bindEvents() { const resetButton = document.querySelector(".example #reset"); runButton.addEventListener("click", () => { - runCalculations(hf, sheetId); + runCalculations(); }); resetButton.addEventListener("click", () => { - resetTable(tableData); + resetTable(); }); } diff --git a/docs/examples/sorting-data/example1.js b/docs/examples/sorting-data/example1.js index 9c91575d5c..57952b6ec4 100644 --- a/docs/examples/sorting-data/example1.js +++ b/docs/examples/sorting-data/example1.js @@ -113,13 +113,6 @@ function renderTable(calculated = false) { tbodyDOM.innerHTML = newTbodyHTML; } -/** - * Replace the values in the table with initial data. - */ -function resetTable() { - renderTable(); -} - const doSortASC = () => { sort(true, () => { renderTable(true); diff --git a/docs/examples/sorting-data/example1.ts b/docs/examples/sorting-data/example1.ts index f300435d32..a28f994e74 100644 --- a/docs/examples/sorting-data/example1.ts +++ b/docs/examples/sorting-data/example1.ts @@ -113,13 +113,6 @@ function renderTable(calculated = false) { tbodyDOM.innerHTML = newTbodyHTML; } -/** - * Replace the values in the table with initial data. - */ -function resetTable() { - renderTable(); -} - const doSortASC = () => { sort(true, () => { renderTable(true); diff --git a/docs/examples/undo-redo/example1.js b/docs/examples/undo-redo/example1.js index a5894deeff..bedb98d8e1 100644 --- a/docs/examples/undo-redo/example1.js +++ b/docs/examples/undo-redo/example1.js @@ -111,7 +111,7 @@ function removeSecondRow() { } hf.removeRows(sheetId, [1, 1]); - renderTable(true); + renderTable(); } /** diff --git a/docs/examples/undo-redo/example1.ts b/docs/examples/undo-redo/example1.ts index 5761d56a04..4333de2b4c 100644 --- a/docs/examples/undo-redo/example1.ts +++ b/docs/examples/undo-redo/example1.ts @@ -107,7 +107,7 @@ function removeSecondRow() { } hf.removeRows(sheetId, [1, 1]); - renderTable(true); + renderTable(); } /** From 6368ae170f8851bf5977d5f2b176e70495bb168c Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Wed, 9 Oct 2024 12:31:59 +0200 Subject: [PATCH 30/41] Disable linter for the docs examples --- .eslintignore | 3 + docs/examples/advanced-usage/example1.ts | 63 +++-- docs/examples/basic-operations/example1.js | 2 +- docs/examples/basic-operations/example1.ts | 256 ++++++++++-------- docs/examples/basic-usage/example1.ts | 34 ++- docs/examples/batch-operations/example1.ts | 85 +++--- .../examples/clipboard-operations/example1.ts | 52 ++-- docs/examples/date-time/example1.js | 4 +- docs/examples/date-time/example1.ts | 45 +-- docs/examples/demo/example1.ts | 78 ++++-- docs/examples/i18n/example1.ts | 91 +++++-- .../examples/localizing-functions/example1.ts | 74 +++-- docs/examples/named-expressions/example1.ts | 53 ++-- docs/examples/sorting-data/example1.js | 2 +- docs/examples/sorting-data/example1.ts | 54 ++-- docs/examples/undo-redo/example1.js | 2 +- docs/examples/undo-redo/example1.ts | 40 +-- 17 files changed, 522 insertions(+), 416 deletions(-) diff --git a/.eslintignore b/.eslintignore index c0a76472bd..1bec93b8cd 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,9 @@ # Common files node_modules +# example files +docs/examples/ + # 3rd party src/interpreter/plugin/3rdparty diff --git a/docs/examples/advanced-usage/example1.ts b/docs/examples/advanced-usage/example1.ts index f58bd729ef..8b7b01d519 100644 --- a/docs/examples/advanced-usage/example1.ts +++ b/docs/examples/advanced-usage/example1.ts @@ -2,44 +2,48 @@ import HyperFormula from 'hyperformula'; /* end:skip-in-compilation */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); // first column represents players' IDs // second column represents players' scores const playersAData = [ - ["1", "2"], - ["2", "3"], - ["3", "5"], - ["4", "7"], - ["5", "13"], - ["6", "17"] + ['1', '2'], + ['2', '3'], + ['3', '5'], + ['4', '7'], + ['5', '13'], + ['6', '17'], ]; + const playersBData = [ - ["7", "19"], - ["8", "31"], - ["9", "61"], - ["10", "89"], - ["11", "107"], - ["12", "127"] + ['7', '19'], + ['8', '31'], + ['9', '61'], + ['10', '89'], + ['11', '107'], + ['12', '127'], ]; // in a cell A1 a formula checks which team is a winning one // in cells A2 and A3 formulas calculate the average score of players const formulasData = [ ['=IF(Formulas!A2>Formulas!A3,"TeamA","TeamB")'], - ["=AVERAGE(TeamA!B1:B6)"], - ["=AVERAGE(TeamB!B1:B6)"] + ['=AVERAGE(TeamA!B1:B6)'], + ['=AVERAGE(TeamB!B1:B6)'], ]; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ - licenseKey: "gpl-v3" + licenseKey: 'gpl-v3', }); const sheetInfo = { - teamA: { sheetName: "TeamA" }, - teamB: { sheetName: "TeamB" }, - formulas: { sheetName: "Formulas" }, + teamA: { sheetName: 'TeamA' }, + teamB: { sheetName: 'TeamB' }, + formulas: { sheetName: 'Formulas' }, }; // add 'TeamA' sheet @@ -57,7 +61,6 @@ hf.addSheet(sheetInfo.formulas.sheetName); // add formulas to that sheet hf.setSheetContent(hf.getSheetId(sheetInfo.formulas.sheetName), formulasData); - /** * Fill the HTML table with data. * @@ -65,15 +68,18 @@ hf.setSheetContent(hf.getSheetId(sheetInfo.formulas.sheetName), formulasData); */ function renderTable(sheetName) { const sheetId = hf.getSheetId(sheetName); - const tbodyDOM = document.querySelector(`.example #${sheetName}-container tbody`); + const tbodyDOM = document.querySelector( + `.example #${sheetName}-container tbody` + ); + const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; + let newTbodyHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); - let cellValue = ""; + let cellValue = ''; if (!hf.isCellEmpty(cellAddress) && !cellHasFormula) { cellValue = hf.getCellValue(cellAddress); @@ -84,7 +90,7 @@ function renderTable(sheetName) { newTbodyHTML += `${cellValue}`; } - newTbodyHTML += ""; + newTbodyHTML += ''; } tbodyDOM.innerHTML = newTbodyHTML; @@ -94,9 +100,10 @@ function renderTable(sheetName) { * Render the result block. */ function renderResult() { - const resultOutputDOM = document.querySelector(".example #result .output"); + const resultOutputDOM = document.querySelector('.example #result .output'); const cellAddress = hf.simpleCellAddressFromString( - `${sheetInfo.formulas.sheetName}!A1`, hf.getSheetId(sheetInfo.formulas.sheetName) + `${sheetInfo.formulas.sheetName}!A1`, + hf.getSheetId(sheetInfo.formulas.sheetName) ); resultOutputDOM.innerHTML = ` @@ -108,9 +115,9 @@ function renderResult() { * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector(".example #run"); + const runButton = document.querySelector('.example #run'); - runButton.addEventListener("click", () => { + runButton.addEventListener('click', () => { renderResult(); }); } diff --git a/docs/examples/basic-operations/example1.js b/docs/examples/basic-operations/example1.js index 17ccaf8efe..6f094daee5 100644 --- a/docs/examples/basic-operations/example1.js +++ b/docs/examples/basic-operations/example1.js @@ -318,7 +318,7 @@ function bindEvents() { */ function doAction(action) { let cellAddress = null; - let inputValues = [ + const inputValues = [ document.querySelector('.example #input-1').value || void 0, document.querySelector('.example #input-2').value || void 0, ]; diff --git a/docs/examples/basic-operations/example1.ts b/docs/examples/basic-operations/example1.ts index 8178f2e53a..af05a4c77b 100644 --- a/docs/examples/basic-operations/example1.ts +++ b/docs/examples/basic-operations/example1.ts @@ -2,7 +2,10 @@ import HyperFormula from 'hyperformula'; /* end:skip-in-compilation */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); const ANIMATION_ENABLED = true; @@ -33,7 +36,7 @@ function getSampleData(rows, columns) { * @type {object} */ const state = { - currentSheet: null + currentSheet: null, }; /** @@ -42,116 +45,117 @@ const state = { * @type {object} */ const inputConfig = { - "add-sheet": { + 'add-sheet': { inputs: [ { - type: "text", - placeholder: "Sheet name" - } + type: 'text', + placeholder: 'Sheet name', + }, ], - buttonText: "Add Sheet", + buttonText: 'Add Sheet', disclaimer: - "For the sake of this demo, the new sheets will be filled with random data." + 'For the sake of this demo, the new sheets will be filled with random data.', }, - "remove-sheet": { + 'remove-sheet': { inputs: [ { - type: "text", - placeholder: "Sheet name" - } + type: 'text', + placeholder: 'Sheet name', + }, ], - buttonText: "Remove Sheet" + buttonText: 'Remove Sheet', }, - "add-rows": { + 'add-rows': { inputs: [ { - type: "number", - placeholder: "Index" + type: 'number', + placeholder: 'Index', }, { - type: "number", - placeholder: "Amount" - } + type: 'number', + placeholder: 'Amount', + }, ], - buttonText: "Add Rows" + buttonText: 'Add Rows', }, - "add-columns": { + 'add-columns': { inputs: [ { - type: "number", - placeholder: "Index" + type: 'number', + placeholder: 'Index', }, { - type: "number", - placeholder: "Amount" - } + type: 'number', + placeholder: 'Amount', + }, ], - buttonText: "Add Columns" + buttonText: 'Add Columns', }, - "remove-rows": { + 'remove-rows': { inputs: [ { - type: "number", - placeholder: "Index" + type: 'number', + placeholder: 'Index', }, { - type: "number", - placeholder: "Amount" - } + type: 'number', + placeholder: 'Amount', + }, ], - buttonText: "Remove Rows" + buttonText: 'Remove Rows', }, - "remove-columns": { + 'remove-columns': { inputs: [ { - type: "number", - placeholder: "Index" + type: 'number', + placeholder: 'Index', }, { - type: "number", - placeholder: "Amount" - } + type: 'number', + placeholder: 'Amount', + }, ], - buttonText: "Remove Columns" + buttonText: 'Remove Columns', }, - "get-value": { + 'get-value': { inputs: [ { - type: "text", - placeholder: "Cell Address" + type: 'text', + placeholder: 'Cell Address', }, { - type: "text", - disabled: "disabled", - placeholder: "" - } + type: 'text', + disabled: 'disabled', + placeholder: '', + }, ], - disclaimer: "Cell addresses format examples: A1, B4, C6.", - buttonText: "Get Value" + disclaimer: 'Cell addresses format examples: A1, B4, C6.', + buttonText: 'Get Value', }, - "set-value": { + 'set-value': { inputs: [ { - type: "text", - placeholder: "Cell Address" + type: 'text', + placeholder: 'Cell Address', }, { - type: "text", - placeholder: "Value" - } + type: 'text', + placeholder: 'Value', + }, ], - disclaimer: "Cell addresses format examples: A1, B4, C6.", - buttonText: "Set Value" - } + disclaimer: 'Cell addresses format examples: A1, B4, C6.', + buttonText: 'Set Value', + }, }; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ - licenseKey: "gpl-v3" + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -state.currentSheet = "InitialSheet"; +state.currentSheet = 'InitialSheet'; + const sheetName = hf.addSheet(state.currentSheet); const sheetId = hf.getSheetId(sheetName); @@ -163,10 +167,10 @@ hf.setSheetContent(sheetId, getSampleData(5, 5)); */ function renderTable() { const sheetId = hf.getSheetId(state.currentSheet); - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; + let newTbodyHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { @@ -174,10 +178,10 @@ function renderTable() { const isEmpty = hf.isCellEmpty(cellAddress); const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = cellHasFormula; - let cellValue = ""; + let cellValue = ''; if (isEmpty) { - cellValue = ""; + cellValue = ''; } else if (!showFormula) { cellValue = hf.getCellValue(cellAddress); } else { @@ -185,13 +189,13 @@ function renderTable() { } newTbodyHTML += ` ${cellValue} `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } tbodyDOM.innerHTML = newTbodyHTML; @@ -202,15 +206,16 @@ function renderTable() { */ function updateSheetDropdown() { const sheetNames = hf.getSheetNames(); - const sheetDropdownDOM = document.querySelector(".example #sheet-select"); - let dropdownContent = ""; + const sheetDropdownDOM = document.querySelector('.example #sheet-select'); + let dropdownContent = ''; - sheetDropdownDOM.innerHTML = ""; + sheetDropdownDOM.innerHTML = ''; - sheetNames.forEach(sheetName => { + sheetNames.forEach((sheetName) => { const isCurrent = sheetName === state.currentSheet; + dropdownContent += ``; }); @@ -223,15 +228,15 @@ function updateSheetDropdown() { * @param {string} action Action chosen from the dropdown. */ function updateForm(action) { - const inputsDOM = document.querySelector(".example #inputs"); - const submitButtonDOM = document.querySelector(".example #inputs button"); - const allInputsDOM = document.querySelectorAll(".example #inputs input"); - const disclaimerDOM = document.querySelector(".example #disclaimer"); + const inputsDOM = document.querySelector('.example #inputs'); + const submitButtonDOM = document.querySelector('.example #inputs button'); + const allInputsDOM = document.querySelectorAll('.example #inputs input'); + const disclaimerDOM = document.querySelector('.example #disclaimer'); // Hide all inputs - allInputsDOM.forEach(input => { - input.style.display = "none"; - input.value = ""; + allInputsDOM.forEach((input) => { + input.style.display = 'none'; + input.value = ''; input.disabled = false; }); @@ -239,7 +244,7 @@ function updateForm(action) { const inputDOM = document.querySelector(`.example #input-${index + 1}`); // Show only those needed - inputDOM.style.display = "block"; + inputDOM.style.display = 'block'; for (const [attribute, value] of Object.entries(inputCfg)) { inputDOM.setAttribute(attribute, value); @@ -251,10 +256,10 @@ function updateForm(action) { if (inputConfig[action].disclaimer) { disclaimerDOM.innerHTML = inputConfig[action].disclaimer; } else { - disclaimerDOM.innerHTML = " "; + disclaimerDOM.innerHTML = ' '; } - inputsDOM.style.display = "block"; + inputsDOM.style.display = 'block'; } /** @@ -263,39 +268,39 @@ function updateForm(action) { * @param {string} message Error message. */ function renderError(message) { - const inputsDOM = document.querySelector(".example #inputs"); - const errorDOM = document.querySelector(".example #error-message"); + const inputsDOM = document.querySelector('.example #inputs'); + const errorDOM = document.querySelector('.example #error-message'); - if (inputsDOM.className.indexOf("error") === -1) { - inputsDOM.className += " error"; + if (inputsDOM.className.indexOf('error') === -1) { + inputsDOM.className += ' error'; } errorDOM.innerText = message; - errorDOM.style.display = "block"; + errorDOM.style.display = 'block'; } /** * Clear the error overlay. */ function clearError() { - const inputsDOM = document.querySelector(".example #inputs"); - const errorDOM = document.querySelector(".example #error-message"); + const inputsDOM = document.querySelector('.example #inputs'); + const errorDOM = document.querySelector('.example #error-message'); - inputsDOM.className = inputsDOM.className.replace(" error", ""); + inputsDOM.className = inputsDOM.className.replace(' error', ''); - errorDOM.innerText = ""; - errorDOM.style.display = "none"; + errorDOM.innerText = ''; + errorDOM.style.display = 'none'; } /** * Bind the events to the buttons. */ function bindEvents() { - const sheetDropdown = document.querySelector(".example #sheet-select"); - const actionDropdown = document.querySelector(".example #action-select"); - const submitButton = document.querySelector(".example #inputs button"); + const sheetDropdown = document.querySelector('.example #sheet-select'); + const actionDropdown = document.querySelector('.example #action-select'); + const submitButton = document.querySelector('.example #inputs button'); - sheetDropdown.addEventListener("change", event => { + sheetDropdown.addEventListener('change', (event) => { state.currentSheet = event.target.value; clearError(); @@ -303,14 +308,14 @@ function bindEvents() { renderTable(); }); - actionDropdown.addEventListener("change", event => { + actionDropdown.addEventListener('change', (event) => { clearError(); updateForm(event.target.value); }); - submitButton.addEventListener("click", event => { - const action = document.querySelector(".example #action-select").value; + submitButton.addEventListener('click', (event) => { + const action = document.querySelector('.example #action-select').value; doAction(action); }); @@ -323,25 +328,29 @@ function bindEvents() { */ function doAction(action) { let cellAddress = null; - let inputValues = [ - document.querySelector(".example #input-1").value || void 0, - document.querySelector(".example #input-2").value || void 0 + const inputValues = [ + document.querySelector('.example #input-1').value || void 0, + document.querySelector('.example #input-2').value || void 0, ]; clearError(); switch (action) { - case "add-sheet": + case 'add-sheet': state.currentSheet = hf.addSheet(inputValues[0]); handleError(() => { - hf.setSheetContent(hf.getSheetId(state.currentSheet), getSampleData(5, 5)); + hf.setSheetContent( + hf.getSheetId(state.currentSheet), + getSampleData(5, 5) + ); }); updateSheetDropdown(); renderTable(); + break; - case "remove-sheet": + case 'remove-sheet': handleError(() => { hf.removeSheet(hf.getSheetId(inputValues[0])); }); @@ -353,55 +362,61 @@ function doAction(action) { } updateSheetDropdown(); + break; - case "add-rows": + case 'add-rows': handleError(() => { hf.addRows(hf.getSheetId(state.currentSheet), [ parseInt(inputValues[0], 10), - parseInt(inputValues[1], 10) + parseInt(inputValues[1], 10), ]); }); renderTable(); + break; - case "add-columns": + case 'add-columns': handleError(() => { hf.addColumns(hf.getSheetId(state.currentSheet), [ parseInt(inputValues[0], 10), - parseInt(inputValues[1], 10) + parseInt(inputValues[1], 10), ]); }); renderTable(); + break; - case "remove-rows": + case 'remove-rows': handleError(() => { hf.removeRows(hf.getSheetId(state.currentSheet), [ parseInt(inputValues[0], 10), - parseInt(inputValues[1], 10) + parseInt(inputValues[1], 10), ]); }); renderTable(); + break; - case "remove-columns": + case 'remove-columns': handleError(() => { hf.removeColumns(hf.getSheetId(state.currentSheet), [ parseInt(inputValues[0], 10), - parseInt(inputValues[1], 10) + parseInt(inputValues[1], 10), ]); }); renderTable(); + break; - case "get-value": - const resultDOM = document.querySelector(".example #input-2"); + case 'get-value': + const resultDOM = document.querySelector('.example #input-2'); + cellAddress = handleError(() => { return hf.simpleCellAddressFromString( inputValues[0], hf.getSheetId(state.currentSheet) ); - }, "Invalid cell address format."); + }, 'Invalid cell address format.'); if (cellAddress !== null) { resultDOM.value = handleError(() => { @@ -410,13 +425,13 @@ function doAction(action) { } break; - case "set-value": + case 'set-value': cellAddress = handleError(() => { return hf.simpleCellAddressFromString( inputValues[0], hf.getSheetId(state.currentSheet) ); - }, "Invalid cell address format."); + }, 'Invalid cell address format.'); if (cellAddress !== null) { handleError(() => { @@ -425,6 +440,7 @@ function doAction(action) { } renderTable(); + break; default: } @@ -445,7 +461,7 @@ function handleError(tryFunc, message = null) { if (e instanceof Error) { renderError(message || e.message); } else { - renderError("Something went wrong"); + renderError('Something went wrong'); } } diff --git a/docs/examples/basic-usage/example1.ts b/docs/examples/basic-usage/example1.ts index 4ec0962143..d256f3d2a0 100644 --- a/docs/examples/basic-usage/example1.ts +++ b/docs/examples/basic-usage/example1.ts @@ -2,18 +2,21 @@ import HyperFormula from 'hyperformula'; /* end:skip-in-compilation */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); -const tableData = [["10", "20", "=SUM(A1,B1)"]]; +const tableData = [['10', '20', '=SUM(A1,B1)']]; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ precisionRounding: 10, - licenseKey: "gpl-v3" + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. @@ -21,7 +24,7 @@ hf.setCellContents( { row: 0, col: 0, - sheet: sheetId + sheet: sheetId, }, tableData ); @@ -30,22 +33,23 @@ hf.setCellContents( * Fill the HTML table with data. */ function renderTable() { - const theadDOM = document.querySelector(".example thead"); - const tbodyDOM = document.querySelector(".example tbody"); + const theadDOM = document.querySelector('.example thead'); + const tbodyDOM = document.querySelector('.example tbody'); const { height, width } = hf.getSheetDimensions(sheetId); - let newTheadHTML = ""; - let newTbodyHTML = ""; + let newTheadHTML = ''; + let newTbodyHTML = ''; for (let row = -1; row < height; row++) { for (let col = 0; col < width; col++) { if (row === -1) { newTheadHTML += ``; + continue; } const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); - let cellValue = ""; + let cellValue = ''; if (!hf.isCellEmpty(cellAddress) && !cellHasFormula) { cellValue = hf.getCellValue(cellAddress); @@ -58,7 +62,7 @@ function renderTable() { `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } tbodyDOM.innerHTML = `${newTbodyHTML}`; @@ -69,14 +73,14 @@ function renderTable() { * Bind the events to the buttons. */ function bindEvents() { - const calculateButton = document.querySelector(".example #calculate"); - const formulaPreview = document.querySelector(".example #address-preview"); - const calculationResult = document.querySelector(".example #result"); + const calculateButton = document.querySelector('.example #calculate'); + const formulaPreview = document.querySelector('.example #address-preview'); + const calculationResult = document.querySelector('.example #result'); const cellAddress = { sheet: sheetId, row: 0, col: 2 }; formulaPreview.innerText = hf.simpleCellAddressToString(cellAddress, sheetId); - calculateButton.addEventListener("click", () => { + calculateButton.addEventListener('click', () => { calculationResult.innerText = hf.getCellValue(cellAddress); }); } diff --git a/docs/examples/batch-operations/example1.ts b/docs/examples/batch-operations/example1.ts index ea353e41dc..f88140f048 100644 --- a/docs/examples/batch-operations/example1.ts +++ b/docs/examples/batch-operations/example1.ts @@ -2,32 +2,35 @@ import HyperFormula from 'hyperformula'; /* end:skip-in-compilation */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); /** * Initial table data. */ const tableData = [ - ["Greg Black", 4.66, "=B1*1.3", "=AVERAGE(B1:C1)", "=SUM(B1:C1)"], - ["Anne Carpenter", 5.25, "=$B$2*30%", "=AVERAGE(B2:C2)", "=SUM(B2:C2)"], - ["Natalie Dem", 3.59, "=B3*2.7+2+1", "=AVERAGE(B3:C3)", "=SUM(B3:C3)"], - ["John Sieg", 12.51, "=B4*(1.22+1)", "=AVERAGE(B4:C4)", "=SUM(B4:C4)"], + ['Greg Black', 4.66, '=B1*1.3', '=AVERAGE(B1:C1)', '=SUM(B1:C1)'], + ['Anne Carpenter', 5.25, '=$B$2*30%', '=AVERAGE(B2:C2)', '=SUM(B2:C2)'], + ['Natalie Dem', 3.59, '=B3*2.7+2+1', '=AVERAGE(B3:C3)', '=SUM(B3:C3)'], + ['John Sieg', 12.51, '=B4*(1.22+1)', '=AVERAGE(B4:C4)', '=SUM(B4:C4)'], [ - "Chris Aklips", + 'Chris Aklips', 7.63, - "=B5*1.1*SUM(10,20)+1", - "=AVERAGE(B5:C5)", - "=SUM(B5:C5)" - ] + '=B5*1.1*SUM(10,20)+1', + '=AVERAGE(B5:C5)', + '=SUM(B5:C5)', + ], ]; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ - licenseKey: "gpl-v3" + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. @@ -35,14 +38,14 @@ hf.setCellContents( { row: 0, col: 0, - sheet: sheetId + sheet: sheetId, }, tableData ); // Add named expressions for the "TOTAL" row. -hf.addNamedExpression("Year_1", "=SUM(main!$B$1:main!$B$5)"); -hf.addNamedExpression("Year_2", "=SUM(main!$C$1:main!$C$5)"); +hf.addNamedExpression('Year_1', '=SUM(main!$B$1:main!$B$5)'); +hf.addNamedExpression('Year_2', '=SUM(main!$C$1:main!$C$5)'); const ANIMATION_ENABLED = true; @@ -52,19 +55,19 @@ const ANIMATION_ENABLED = true; * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. */ function renderTable(calculated = false) { - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; - const totals = ["=SUM(Year_1)", "=SUM(Year_2)"]; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const totals = ['=SUM(Year_1)', '=SUM(Year_2)']; const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; - let totalRowsHTML = ""; + let newTbodyHTML = ''; + let totalRowsHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = calculated || !cellHasFormula; - let cellValue = ""; + let cellValue = ''; if (!hf.isCellEmpty(cellAddress) && showFormula) { cellValue = hf.getCellValue(cellAddress); @@ -77,30 +80,30 @@ function renderTable(calculated = false) { } newTbodyHTML += ` ${cellValue} `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } totalRowsHTML = ` TOTAL ${ - calculated - ? hf.calculateFormula(totals[0], sheetId).toFixed(2) - : totals[0] - } + calculated + ? hf.calculateFormula(totals[0], sheetId).toFixed(2) + : totals[0] + }
${ - calculated - ? hf.calculateFormula(totals[1], sheetId).toFixed(2) - : totals[1] - } + calculated + ? hf.calculateFormula(totals[1], sheetId).toFixed(2) + : totals[1] + } `; @@ -116,19 +119,19 @@ let IS_CALCULATED = false; * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector(".example #run"); - const resetButton = document.querySelector(".example #reset"); - const calculatedCheckbox = document.querySelector(".example #isCalculated"); + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); + const calculatedCheckbox = document.querySelector('.example #isCalculated'); - runButton.addEventListener("click", () => { + runButton.addEventListener('click', () => { runBatchOperations(); }); - resetButton.addEventListener("click", () => { + resetButton.addEventListener('click', () => { resetTableData(); }); - calculatedCheckbox.addEventListener("change", e => { + calculatedCheckbox.addEventListener('change', (e) => { if (e.target.checked) { renderTable(true); } else { @@ -152,10 +155,10 @@ function resetTableData() { */ function runBatchOperations() { hf.batch(() => { - hf.setCellContents({ col: 1, row: 0, sheet: sheetId }, [["=B4"]]); - hf.setCellContents({ col: 1, row: 1, sheet: sheetId }, [["=B4"]]); - hf.setCellContents({ col: 1, row: 2, sheet: sheetId }, [["=B4"]]); - hf.setCellContents({ col: 1, row: 4, sheet: sheetId }, [["=B4"]]); + hf.setCellContents({ col: 1, row: 0, sheet: sheetId }, [['=B4']]); + hf.setCellContents({ col: 1, row: 1, sheet: sheetId }, [['=B4']]); + hf.setCellContents({ col: 1, row: 2, sheet: sheetId }, [['=B4']]); + hf.setCellContents({ col: 1, row: 4, sheet: sheetId }, [['=B4']]); }); renderTable(IS_CALCULATED); diff --git a/docs/examples/clipboard-operations/example1.ts b/docs/examples/clipboard-operations/example1.ts index 476b4253b9..0dc5d8365c 100644 --- a/docs/examples/clipboard-operations/example1.ts +++ b/docs/examples/clipboard-operations/example1.ts @@ -2,24 +2,27 @@ import HyperFormula from 'hyperformula'; /* end:skip-in-compilation */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); /** * Initial table data. */ const tableData = [ - ["Greg", "Black", '=CONCATENATE(A1, " ",B1)'], - ["Anne", "Carpenter", '=CONCATENATE(A2, " ", B2)'], - ["Chris", "Aklips", '=CONCATENATE(A3, " ",B3)'] + ['Greg', 'Black', '=CONCATENATE(A1, " ",B1)'], + ['Anne', 'Carpenter', '=CONCATENATE(A2, " ", B2)'], + ['Chris', 'Aklips', '=CONCATENATE(A3, " ",B3)'], ]; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ - licenseKey: "gpl-v3" + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); /** @@ -30,7 +33,7 @@ function reinitializeData() { { row: 0, col: 0, - sheet: sheetId + sheet: sheetId, }, tableData ); @@ -40,23 +43,23 @@ function reinitializeData() { * Bind the events to the buttons. */ function bindEvents() { - const copyButton = document.querySelector(".example #copy"); - const pasteButton = document.querySelector(".example #paste"); - const resetButton = document.querySelector(".example #reset"); + const copyButton = document.querySelector('.example #copy'); + const pasteButton = document.querySelector('.example #paste'); + const resetButton = document.querySelector('.example #reset'); - copyButton.addEventListener("click", () => { + copyButton.addEventListener('click', () => { copy(); - updateCopyInfo("Second row copied"); + updateCopyInfo('Second row copied'); }); - pasteButton.addEventListener("click", () => { + pasteButton.addEventListener('click', () => { paste(); - updateCopyInfo("Pasted into the first row"); + updateCopyInfo('Pasted into the first row'); }); - resetButton.addEventListener("click", () => { + resetButton.addEventListener('click', () => { reinitializeData(); - updateCopyInfo(""); + updateCopyInfo(''); renderTable(); }); } @@ -65,7 +68,10 @@ function bindEvents() { * Copy the second row. */ function copy() { - return hf.copy({start: { sheet: 0, col: 0, row: 1 }, end: { sheet: 0, col: 2, row: 1 }}); + return hf.copy({ + start: { sheet: 0, col: 0, row: 1 }, + end: { sheet: 0, col: 2, row: 1 }, + }); } /** @@ -82,15 +88,15 @@ const ANIMATION_ENABLED = true; * Fill the HTML table with data. */ function renderTable() { - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; + let newTbodyHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; - let cellValue = ""; + let cellValue = ''; if (!hf.isCellEmpty(cellAddress)) { cellValue = hf.getCellValue(cellAddress); @@ -101,7 +107,7 @@ function renderTable() { `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } tbodyDOM.innerHTML = newTbodyHTML; @@ -113,7 +119,7 @@ function renderTable() { * @param {string} message Message to display. */ function updateCopyInfo(message) { - const copyInfoDOM = document.querySelector(".example #copyInfo"); + const copyInfoDOM = document.querySelector('.example #copyInfo'); copyInfoDOM.innerText = message; } diff --git a/docs/examples/date-time/example1.js b/docs/examples/date-time/example1.js index 71ca4b278e..87278f91c4 100644 --- a/docs/examples/date-time/example1.js +++ b/docs/examples/date-time/example1.js @@ -80,7 +80,7 @@ function renderTable(calculated = false) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = calculated || !cellHasFormula; - let cellValue = displayValue(cellAddress, showFormula); + const cellValue = displayValue(cellAddress, showFormula); newTbodyHTML += ` { return { year: momentDate.year(), month: momentDate.month() + 1, - day: momentDate.date() + day: momentDate.date(), }; } }; @@ -30,26 +33,26 @@ const customParseDate = (dateString, dateFormat) => { * @param {{month: *, year: *, day: *}} dateObject Object with date-related information. * @returns {string} Formatted date string. */ -const getFormattedDate = dateObject => { +const getFormattedDate = (dateObject) => { dateObject.month -= 1; - return moment(dateObject).format("MMM D YY"); + return moment(dateObject).format('MMM D YY'); }; /** * Initial table data. */ -const tableData = [["Jan 31 00", "Jun 2 01", "=B1-A1"]]; +const tableData = [['Jan 31 00', 'Jun 2 01', '=B1-A1']]; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ parseDateTime: customParseDate, - dateFormats: ["MMM D YY"], - licenseKey: "gpl-v3" + dateFormats: ['MMM D YY'], + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. @@ -57,7 +60,7 @@ hf.setCellContents( { row: 0, col: 0, - sheet: sheetId + sheet: sheetId, }, tableData ); @@ -68,20 +71,20 @@ hf.setCellContents( * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. */ function renderTable(calculated = false) { - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; + let newTbodyHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = calculated || !cellHasFormula; - let cellValue = displayValue(cellAddress, showFormula); + const cellValue = displayValue(cellAddress, showFormula); newTbodyHTML += ` ${cellValue} `; @@ -99,8 +102,8 @@ function renderTable(calculated = false) { */ function displayValue(cellAddress, showFormula) { // Declare which columns should display the raw source data, instead of the data from HyperFormula. - let sourceColumns = [0, 1]; - let cellValue = ""; + const sourceColumns = [0, 1]; + let cellValue = ''; if (sourceColumns.includes(cellAddress.col)) { cellValue = getFormattedDate(hf.numberToDate(hf.getCellValue(cellAddress))); @@ -133,14 +136,14 @@ function resetTable() { * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector(".example #run"); - const resetButton = document.querySelector(".example #reset"); + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); - runButton.addEventListener("click", () => { + runButton.addEventListener('click', () => { runCalculations(); }); - resetButton.addEventListener("click", () => { + resetButton.addEventListener('click', () => { resetTable(); }); } diff --git a/docs/examples/demo/example1.ts b/docs/examples/demo/example1.ts index 9f6d341cb0..63602fa244 100644 --- a/docs/examples/demo/example1.ts +++ b/docs/examples/demo/example1.ts @@ -2,44 +2,58 @@ import HyperFormula from 'hyperformula'; /* end:skip-in-compilation */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); const tableData = [ - ["Greg Black", 4.66, "=B1*1.3", "=AVERAGE(B1:C1)", "=SUM(B1:C1)"], - ["Anne Carpenter", 5.25, "=$B$2*30%", "=AVERAGE(B2:C2)", "=SUM(B2:C2)"], - ["Natalie Dem", 3.59, "=B3*2.7+2+1", "=AVERAGE(B3:C3)", "=SUM(B3:C3)"], - ["John Sieg", 12.51, "=B4*(1.22+1)", "=AVERAGE(B4:C4)", "=SUM(B4:C4)"], - ["Chris Aklips", 7.63, "=B5*1.1*SUM(10,20)+1", "=AVERAGE(B5:C5)", "=SUM(B5:C5)"] + ['Greg Black', 4.66, '=B1*1.3', '=AVERAGE(B1:C1)', '=SUM(B1:C1)'], + ['Anne Carpenter', 5.25, '=$B$2*30%', '=AVERAGE(B2:C2)', '=SUM(B2:C2)'], + ['Natalie Dem', 3.59, '=B3*2.7+2+1', '=AVERAGE(B3:C3)', '=SUM(B3:C3)'], + ['John Sieg', 12.51, '=B4*(1.22+1)', '=AVERAGE(B4:C4)', '=SUM(B4:C4)'], + [ + 'Chris Aklips', + 7.63, + '=B5*1.1*SUM(10,20)+1', + '=AVERAGE(B5:C5)', + '=SUM(B5:C5)', + ], ]; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ - licenseKey: "gpl-v3" + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. -hf.setCellContents({ - row: 0, col: 0, sheet: sheetId -}, tableData); +hf.setCellContents( + { + row: 0, + col: 0, + sheet: sheetId, + }, + tableData +); // Add named expressions for the "TOTAL" row. -hf.addNamedExpression("Year_1", "=SUM(main!$B$1:main!$B$5)"); -hf.addNamedExpression("Year_2", "=SUM(main!$C$1:main!$C$5)"); +hf.addNamedExpression('Year_1', '=SUM(main!$B$1:main!$B$5)'); +hf.addNamedExpression('Year_2', '=SUM(main!$C$1:main!$C$5)'); // Bind the events to the buttons. function bindEvents() { - const runButton = document.querySelector(".example #run"); - const resetButton = document.querySelector(".example #reset"); + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); - runButton.addEventListener("click", () => { + runButton.addEventListener('click', () => { runCalculations(); }); - resetButton.addEventListener("click", () => { + resetButton.addEventListener('click', () => { resetTable(); }); } @@ -52,19 +66,19 @@ const ANIMATION_ENABLED = true; * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. */ function renderTable(calculated = false) { - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; - const totals = ["=SUM(Year_1)", "=SUM(Year_2)"]; - const {height, width} = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; - let totalRowsHTML = ""; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const totals = ['=SUM(Year_1)', '=SUM(Year_2)']; + const { height, width } = hf.getSheetDimensions(sheetId); + let newTbodyHTML = ''; + let totalRowsHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { - const cellAddress = {sheet: sheetId, col, row}; + const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = calculated || !cellHasFormula; - let cellValue = ""; + let cellValue = ''; if (!hf.isCellEmpty(cellAddress) && showFormula) { cellValue = hf.getCellValue(cellAddress); @@ -76,21 +90,27 @@ function renderTable(calculated = false) { cellValue = hf.getCellFormula(cellAddress); } - newTbodyHTML += ` + newTbodyHTML += ` ${cellValue} `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } totalRowsHTML = ` TOTAL - ${calculated ? hf.calculateFormula(totals[0], sheetId).toFixed(2) : totals[0]} + ${ + calculated ? hf.calculateFormula(totals[0], sheetId).toFixed(2) : totals[0] + } - ${calculated ? hf.calculateFormula(totals[1], sheetId).toFixed(2) : totals[1]} + ${ + calculated ? hf.calculateFormula(totals[1], sheetId).toFixed(2) : totals[1] + } `; diff --git a/docs/examples/i18n/example1.ts b/docs/examples/i18n/example1.ts index 564983f62e..cb6a1b9646 100644 --- a/docs/examples/i18n/example1.ts +++ b/docs/examples/i18n/example1.ts @@ -1,25 +1,58 @@ /* start:skip-in-compilation */ import HyperFormula from 'hyperformula'; -import enUS from "hyperformula/es/i18n/languages/enUS"; -import moment from "moment"; +import enUS from 'hyperformula/es/i18n/languages/enUS'; +import moment from 'moment'; /* end:skip-in-compilation */ /* start:skip-in-sandbox */ const enUS = HyperFormula.languages.enUS; /* end:skip-in-sandbox */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); /** * Initial table data. */ const tableData = [ - ["Greg Black", "11:45 AM", "05/23/1989", "=YEAR(NOW())-YEAR(C1)", "$80,000.00"], - ["Anne Carpenter", "12:30 PM", "01/01/1980", "=YEAR(NOW())-YEAR(C2)", "$95,000.00"], - ["Natalie Dem", "1:30 PM", "12/13/1973", "=YEAR(NOW())-YEAR(C3)","$78,500.00"], - ["John Sieg", "2:00 PM", "10/31/1995", "=YEAR(NOW())-YEAR(C4)", "$114,000.00"], - ["Chris Aklips", "11:30 AM", "08/18/1987", "=YEAR(NOW())-YEAR(C5)", "$71,900.00"], - ["AVERAGE", null, null, "=AVERAGE(D1:D5)", "=AVERAGE(E1:E5)"] + [ + 'Greg Black', + '11:45 AM', + '05/23/1989', + '=YEAR(NOW())-YEAR(C1)', + '$80,000.00', + ], + [ + 'Anne Carpenter', + '12:30 PM', + '01/01/1980', + '=YEAR(NOW())-YEAR(C2)', + '$95,000.00', + ], + [ + 'Natalie Dem', + '1:30 PM', + '12/13/1973', + '=YEAR(NOW())-YEAR(C3)', + '$78,500.00', + ], + [ + 'John Sieg', + '2:00 PM', + '10/31/1995', + '=YEAR(NOW())-YEAR(C4)', + '$114,000.00', + ], + [ + 'Chris Aklips', + '11:30 AM', + '08/18/1987', + '=YEAR(NOW())-YEAR(C5)', + '$71,900.00', + ], + ['AVERAGE', null, null, '=AVERAGE(D1:D5)', '=AVERAGE(E1:E5)'], ]; const config = { @@ -31,7 +64,7 @@ const config = { functionArgSeparator: ';', currencySymbol: ['$', 'USD'], localeLang: 'en-US', - licenseKey: "gpl-v3", + licenseKey: 'gpl-v3', }; HyperFormula.registerLanguage('enUS', enUS); @@ -40,7 +73,7 @@ HyperFormula.registerLanguage('enUS', enUS); const hf = HyperFormula.buildEmpty(config); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. @@ -48,7 +81,7 @@ hf.setCellContents( { row: 0, col: 0, - sheet: sheetId + sheet: sheetId, }, tableData ); @@ -62,7 +95,7 @@ const columnTypes = ['string', 'time', 'date', 'number', 'currency']; */ function formatCellValue(cellAddress) { if (hf.isCellEmpty(cellAddress)) { - return ""; + return ''; } if (columnTypes[cellAddress.col] === 'time') { @@ -74,10 +107,10 @@ function formatCellValue(cellAddress) { } if (columnTypes[cellAddress.col] === 'currency') { - return formatCurrency((hf.getCellValue(cellAddress))); + return formatCurrency(hf.getCellValue(cellAddress)); } - return hf.getCellValue(cellAddress) + return hf.getCellValue(cellAddress); } /** @@ -89,7 +122,7 @@ function formatDate(dateObject) { dateObject.month -= 1; return moment(dateObject).format('MM/DD/YYYY'); -}; +} /** * Time formatting function. @@ -98,7 +131,7 @@ function formatDate(dateObject) { */ function formatTime(dateTimeObject) { return moment(dateTimeObject).format('h:mm A'); -}; +} /** * Currency formatting function. @@ -110,7 +143,7 @@ function formatCurrency(value) { style: 'currency', currency: 'USD', }); -}; +} /** * Fill the HTML table with data. @@ -118,26 +151,28 @@ function formatCurrency(value) { * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. */ function renderTable(calculated = false) { - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; + let newTbodyHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = cellHasFormula && !calculated; - const displayValue = showFormula ? hf.getCellFormula(cellAddress) : formatCellValue(cellAddress); + const displayValue = showFormula + ? hf.getCellFormula(cellAddress) + : formatCellValue(cellAddress); newTbodyHTML += ` ${displayValue} `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } tbodyDOM.innerHTML = newTbodyHTML; @@ -161,14 +196,14 @@ function resetTable() { * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector(".example #run"); - const resetButton = document.querySelector(".example #reset"); + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); - runButton.addEventListener("click", () => { + runButton.addEventListener('click', () => { runCalculations(); }); - resetButton.addEventListener("click", () => { + resetButton.addEventListener('click', () => { resetTable(); }); } diff --git a/docs/examples/localizing-functions/example1.ts b/docs/examples/localizing-functions/example1.ts index 68e9a365f1..b6ad79d8b3 100644 --- a/docs/examples/localizing-functions/example1.ts +++ b/docs/examples/localizing-functions/example1.ts @@ -1,45 +1,45 @@ /* start:skip-in-compilation */ import HyperFormula from 'hyperformula'; -import frFR from "hyperformula/es/i18n/languages/frFR"; +import frFR from 'hyperformula/es/i18n/languages/frFR'; /* end:skip-in-compilation */ /* start:skip-in-sandbox */ const frFR = HyperFormula.languages.frFR; /* end:skip-in-sandbox */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); /** * Initial table data. */ const tableData = [ - ["Greg Black", 4.66, "=B1*1.3", "=MOYENNE(B1:C1)", "=SOMME(B1:C1)"], - ["Anne Carpenter", 5.25, "=$B$2*30%", "=MOYENNE(B2:C2)", "=SOMME(B2:C2)"], - ["Natalie Dem", 3.59, "=B3*2.7+2+1", "=MOYENNE(B3:C3)", "=SOMME(B3:C3)"], - ["John Sieg", 12.51, "=B4*(1.22+1)", "=MOYENNE(B4:C4)", "=SOMME(B4:C4)"], + ['Greg Black', 4.66, '=B1*1.3', '=MOYENNE(B1:C1)', '=SOMME(B1:C1)'], + ['Anne Carpenter', 5.25, '=$B$2*30%', '=MOYENNE(B2:C2)', '=SOMME(B2:C2)'], + ['Natalie Dem', 3.59, '=B3*2.7+2+1', '=MOYENNE(B3:C3)', '=SOMME(B3:C3)'], + ['John Sieg', 12.51, '=B4*(1.22+1)', '=MOYENNE(B4:C4)', '=SOMME(B4:C4)'], [ - "Chris Aklips", + 'Chris Aklips', 7.63, - "=B5*1.1*SUM(10,20)+1", - "=MOYENNE(B5:C5)", - "=SOMME(B5:C5)" - ] + '=B5*1.1*SUM(10,20)+1', + '=MOYENNE(B5:C5)', + '=SOMME(B5:C5)', + ], ]; // register language -HyperFormula.registerLanguage( - "frFR", - frFR -); +HyperFormula.registerLanguage('frFR', frFR); // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ - language: "frFR", - licenseKey: "gpl-v3" + language: 'frFR', + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. @@ -47,14 +47,14 @@ hf.setCellContents( { row: 0, col: 0, - sheet: sheetId + sheet: sheetId, }, tableData ); // Add named expressions for the "TOTAL" row. -hf.addNamedExpression("Year_1", "=SOMME(main!$B$1:main!$B$5)"); -hf.addNamedExpression("Year_2", "=SOMME(main!$C$1:main!$C$5)"); +hf.addNamedExpression('Year_1', '=SOMME(main!$B$1:main!$B$5)'); +hf.addNamedExpression('Year_2', '=SOMME(main!$C$1:main!$C$5)'); /** * Fill the HTML table with data. @@ -62,19 +62,19 @@ hf.addNamedExpression("Year_2", "=SOMME(main!$C$1:main!$C$5)"); * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. */ function renderTable(calculated = false) { - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; - const totals = ["=SOMME(Year_1)", "=SOMME(Year_2)"]; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; + const totals = ['=SOMME(Year_1)', '=SOMME(Year_2)']; const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; - let totalRowsHTML = ""; + let newTbodyHTML = ''; + let totalRowsHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = calculated || !cellHasFormula; - let cellValue = ""; + let cellValue = ''; if (!hf.isCellEmpty(cellAddress) && showFormula) { cellValue = hf.getCellValue(cellAddress); @@ -87,29 +87,25 @@ function renderTable(calculated = false) { } newTbodyHTML += ` ${cellValue} `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } totalRowsHTML = ` TOTAL ${ - calculated - ? hf.calculateFormula(totals[0], sheetId).toFixed(2) - : totals[0] + calculated ? hf.calculateFormula(totals[0], sheetId).toFixed(2) : totals[0] } ${ - calculated - ? hf.calculateFormula(totals[1], sheetId).toFixed(2) - : totals[1] + calculated ? hf.calculateFormula(totals[1], sheetId).toFixed(2) : totals[1] } @@ -138,14 +134,14 @@ function resetTable() { * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector(".example #run"); - const resetButton = document.querySelector(".example #reset"); + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); - runButton.addEventListener("click", () => { + runButton.addEventListener('click', () => { runCalculations(); }); - resetButton.addEventListener("click", () => { + resetButton.addEventListener('click', () => { resetTable(); }); } diff --git a/docs/examples/named-expressions/example1.ts b/docs/examples/named-expressions/example1.ts index 19bfabead5..2691722b93 100644 --- a/docs/examples/named-expressions/example1.ts +++ b/docs/examples/named-expressions/example1.ts @@ -2,7 +2,10 @@ import HyperFormula from 'hyperformula'; /* end:skip-in-compilation */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); /** * Initial table data. @@ -11,17 +14,17 @@ const tableData = [ [10, 20, 20, 30], [50, 60, 70, 80], [90, 100, 110, 120], - ["=myOneCell", "=myTwoCells", "=myOneColumn", "=myTwoColumns"], - ["=myFormula+myNumber+34", "=myText", "=myOneRow", "=myTwoRows"] + ['=myOneCell', '=myTwoCells', '=myOneColumn', '=myTwoColumns'], + ['=myFormula+myNumber+34', '=myText', '=myOneRow', '=myTwoRows'], ]; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ - licenseKey: "gpl-v3" + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. @@ -29,21 +32,21 @@ hf.setCellContents( { row: 0, col: 0, - sheet: sheetId + sheet: sheetId, }, tableData ); // Add named expressions -hf.addNamedExpression("myOneCell", "=main!$A$1"); -hf.addNamedExpression("myTwoCells", "=SUM(main!$A$1, main!$A$2)"); -hf.addNamedExpression("myOneColumn", "=SUM(main!$A$1:main!$A$3)"); -hf.addNamedExpression("myTwoColumns", "=SUM(main!$A$1:main!$B$3)"); -hf.addNamedExpression("myOneRow", "=SUM(main!$A$1:main!$D$1)"); -hf.addNamedExpression("myTwoRows", "=SUM(main!$A$1:main!$D$2)"); -hf.addNamedExpression("myFormula", "=SUM(0, 1, 1, 2, 3, 5, 8, 13)"); -hf.addNamedExpression("myNumber", "=21"); -hf.addNamedExpression("myText", "Apollo 11"); +hf.addNamedExpression('myOneCell', '=main!$A$1'); +hf.addNamedExpression('myTwoCells', '=SUM(main!$A$1, main!$A$2)'); +hf.addNamedExpression('myOneColumn', '=SUM(main!$A$1:main!$A$3)'); +hf.addNamedExpression('myTwoColumns', '=SUM(main!$A$1:main!$B$3)'); +hf.addNamedExpression('myOneRow', '=SUM(main!$A$1:main!$D$1)'); +hf.addNamedExpression('myTwoRows', '=SUM(main!$A$1:main!$D$2)'); +hf.addNamedExpression('myFormula', '=SUM(0, 1, 1, 2, 3, 5, 8, 13)'); +hf.addNamedExpression('myNumber', '=21'); +hf.addNamedExpression('myText', 'Apollo 11'); /** * Fill the HTML table with data. @@ -51,18 +54,18 @@ hf.addNamedExpression("myText", "Apollo 11"); * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. */ function renderTable(calculated = false) { - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; + let newTbodyHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = calculated || !cellHasFormula; - let cellValue = ""; + let cellValue = ''; if (!hf.isCellEmpty(cellAddress) && showFormula) { cellValue = hf.getCellValue(cellAddress); @@ -71,13 +74,13 @@ function renderTable(calculated = false) { } newTbodyHTML += ` ${cellValue} `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } tbodyDOM.innerHTML = newTbodyHTML; @@ -101,14 +104,14 @@ function resetTable() { * Bind the events to the buttons. */ function bindEvents() { - const runButton = document.querySelector(".example #run"); - const resetButton = document.querySelector(".example #reset"); + const runButton = document.querySelector('.example #run'); + const resetButton = document.querySelector('.example #reset'); - runButton.addEventListener("click", () => { + runButton.addEventListener('click', () => { runCalculations(); }); - resetButton.addEventListener("click", () => { + resetButton.addEventListener('click', () => { resetTable(); }); } diff --git a/docs/examples/sorting-data/example1.js b/docs/examples/sorting-data/example1.js index 57952b6ec4..65699d0082 100644 --- a/docs/examples/sorting-data/example1.js +++ b/docs/examples/sorting-data/example1.js @@ -50,7 +50,7 @@ function sort(ascending, callback) { const rowCount = hf.getSheetDimensions(sheetId).height; const colValues = []; let newOrder = null; - let newOrderMapping = []; + const newOrderMapping = []; for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) { colValues.push({ diff --git a/docs/examples/sorting-data/example1.ts b/docs/examples/sorting-data/example1.ts index a28f994e74..482880c860 100644 --- a/docs/examples/sorting-data/example1.ts +++ b/docs/examples/sorting-data/example1.ts @@ -2,29 +2,32 @@ import HyperFormula from 'hyperformula'; /* end:skip-in-compilation */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); /** * Initial table data. */ const tableData = [ - ["Greg Black", "100"], - ["Anne Carpenter", "=SUM(100,100)"], - ["Natalie Dem", "500"], - ["John Sieg", "50"], - ["Chris Aklips", "20"], - ["Bart Hoopoe", "700"], - ["Chris Site", "80"], - ["Agnes Whitey", "90"] + ['Greg Black', '100'], + ['Anne Carpenter', '=SUM(100,100)'], + ['Natalie Dem', '500'], + ['John Sieg', '50'], + ['Chris Aklips', '20'], + ['Bart Hoopoe', '700'], + ['Chris Site', '80'], + ['Agnes Whitey', '90'], ]; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ - licenseKey: "gpl-v3" + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. @@ -32,7 +35,7 @@ hf.setCellContents( { row: 0, col: 0, - sheet: sheetId + sheet: sheetId, }, tableData ); @@ -47,7 +50,7 @@ function sort(ascending, callback) { const rowCount = hf.getSheetDimensions(sheetId).height; const colValues = []; let newOrder = null; - let newOrderMapping = []; + const newOrderMapping = []; for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) { colValues.push({ @@ -55,13 +58,14 @@ function sort(ascending, callback) { value: hf.getCellValue({ sheet: sheetId, col: 1, - row: rowIndex - }) + row: rowIndex, + }), }); } colValues.sort((objA, objB) => { const delta = objA.value - objB.value; + return ascending ? delta : -delta; }); @@ -82,17 +86,17 @@ function sort(ascending, callback) { * @param {boolean} calculated `true` if it should render calculated values, `false` otherwise. */ function renderTable(calculated = false) { - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; + let newTbodyHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); const showFormula = calculated || !cellHasFormula; - let cellValue = ""; + let cellValue = ''; if (!hf.isCellEmpty(cellAddress) && showFormula) { cellValue = hf.getCellValue(cellAddress); @@ -101,13 +105,13 @@ function renderTable(calculated = false) { } newTbodyHTML += ` ${cellValue} `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } tbodyDOM.innerHTML = newTbodyHTML; @@ -129,14 +133,14 @@ const doSortDESC = () => { * Bind the events to the buttons. */ function bindEvents() { - const ascSort = document.querySelector(".example #asc"); - const descSort = document.querySelector(".example #desc"); + const ascSort = document.querySelector('.example #asc'); + const descSort = document.querySelector('.example #desc'); - ascSort.addEventListener("click", () => { + ascSort.addEventListener('click', () => { doSortASC(); }); - descSort.addEventListener("click", () => { + descSort.addEventListener('click', () => { doSortDESC(); }); } diff --git a/docs/examples/undo-redo/example1.js b/docs/examples/undo-redo/example1.js index bedb98d8e1..18afc75e53 100644 --- a/docs/examples/undo-redo/example1.js +++ b/docs/examples/undo-redo/example1.js @@ -48,7 +48,7 @@ function renderTable() { for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; - let cellValue = hf.getCellValue(cellAddress); + const cellValue = hf.getCellValue(cellAddress); newTbodyHTML += ` ${cellValue} diff --git a/docs/examples/undo-redo/example1.ts b/docs/examples/undo-redo/example1.ts index 4333de2b4c..80b0201bea 100644 --- a/docs/examples/undo-redo/example1.ts +++ b/docs/examples/undo-redo/example1.ts @@ -2,20 +2,26 @@ import HyperFormula from 'hyperformula'; /* end:skip-in-compilation */ -console.log(`%c Using HyperFormula ${HyperFormula.version}`, 'color: blue; font-weight: bold'); +console.log( + `%c Using HyperFormula ${HyperFormula.version}`, + 'color: blue; font-weight: bold' +); /** * Initial table data. */ -const tableData = [["Greg", "2"], ["Chris", "4"]]; +const tableData = [ + ['Greg', '2'], + ['Chris', '4'], +]; // Create an empty HyperFormula instance. const hf = HyperFormula.buildEmpty({ - licenseKey: "gpl-v3" + licenseKey: 'gpl-v3', }); // Add a new sheet and get its id. -const sheetName = hf.addSheet("main"); +const sheetName = hf.addSheet('main'); const sheetId = hf.getSheetId(sheetName); // Fill the HyperFormula sheet with data. @@ -23,7 +29,7 @@ hf.setCellContents( { row: 0, col: 0, - sheet: sheetId + sheet: sheetId, }, tableData ); @@ -35,22 +41,22 @@ hf.clearUndoStack(); * Fill the HTML table with data. */ function renderTable() { - const tbodyDOM = document.querySelector(".example tbody"); - const updatedCellClass = ANIMATION_ENABLED ? "updated-cell" : ""; + const tbodyDOM = document.querySelector('.example tbody'); + const updatedCellClass = ANIMATION_ENABLED ? 'updated-cell' : ''; const { height, width } = hf.getSheetDimensions(sheetId); - let newTbodyHTML = ""; + let newTbodyHTML = ''; for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; - let cellValue = hf.getCellValue(cellAddress); + const cellValue = hf.getCellValue(cellAddress); newTbodyHTML += ` ${cellValue} `; } - newTbodyHTML += ""; + newTbodyHTML += ''; } tbodyDOM.innerHTML = newTbodyHTML; @@ -60,9 +66,9 @@ function renderTable() { * Clear the existing information. */ function clearInfo() { - const infoBoxDOM = document.querySelector(".example #info-box"); + const infoBoxDOM = document.querySelector('.example #info-box'); - infoBoxDOM.innerHTML = " "; + infoBoxDOM.innerHTML = ' '; } /** @@ -71,7 +77,7 @@ function clearInfo() { * @param {string} message Message to display. */ function displayInfo(message) { - const infoBoxDOM = document.querySelector(".example #info-box"); + const infoBoxDOM = document.querySelector('.example #info-box'); infoBoxDOM.innerText = message; } @@ -80,14 +86,14 @@ function displayInfo(message) { * Bind the events to the buttons. */ function bindEvents() { - const removeRowButton = document.querySelector(".example #remove-row"); - const undoButton = document.querySelector(".example #undo"); + const removeRowButton = document.querySelector('.example #remove-row'); + const undoButton = document.querySelector('.example #undo'); - removeRowButton.addEventListener("click", () => { + removeRowButton.addEventListener('click', () => { removeSecondRow(); }); - undoButton.addEventListener("click", () => { + undoButton.addEventListener('click', () => { undo(); }); } From 213f34238d10d6bfdde09cf841f795e677774523 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 10 Oct 2024 13:19:34 +0200 Subject: [PATCH 31/41] Tweak the styling of demo example --- docs/examples/advanced-usage/example1.css | 87 ++++++++--- docs/examples/basic-operations/example1.css | 146 +++++++----------- docs/examples/basic-usage/example1.css | 78 +++++++--- docs/examples/batch-operations/example1.css | 62 +++++--- .../clipboard-operations/example1.css | 59 +++++-- docs/examples/date-time/example1.css | 60 +++++-- docs/examples/demo/example1.css | 69 +++++++-- docs/examples/example1.css | 129 ++++++++++++++++ docs/examples/i18n/example1.css | 59 +++++-- .../localizing-functions/example1.css | 62 +++++--- docs/examples/named-expressions/example1.css | 64 +++++--- docs/examples/sorting-data/example1.css | 59 +++++-- docs/examples/undo-redo/example1.css | 55 +++++-- 13 files changed, 703 insertions(+), 286 deletions(-) create mode 100644 docs/examples/example1.css diff --git a/docs/examples/advanced-usage/example1.css b/docs/examples/advanced-usage/example1.css index 7f91fd7c65..2f9f5d066c 100644 --- a/docs/examples/advanced-usage/example1.css +++ b/docs/examples/advanced-usage/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,50 +39,81 @@ color: #1c49e4; } +/* labels */ + +.example label { + display: inline-block; + margin-left: 5px; +} + +/* table */ + .example table { table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; } -.example table tbody tr td, -.example table tbody tr th { +.example table tr td, +.example table tr th { overflow: hidden; text-overflow: ellipsis; - padding: .15em; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; } -.example #Formulas-container table tbody tr td { - overflow-wrap: break-word; +.example table thead tr th span { + counter-increment: col-counter; } -.example #result { - border: 1px solid #1c49e433; - background-color: #1c49e405; - border-radius: 0.2em; - padding: 10px; +/* table: first column */ + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; } -.example #result span:first-child { - margin: 0 10px; +.example table thead tr th:first-child { + padding-left: 40px; } -.example #result span.output span { - animation-name: cell-appear; - animation-duration: 0.2s; - margin: 0; +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; } -.example #data-preview { - display: flex; - flex-direction: column; - justify-content: space-between; +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; } -.example .scores { - display: flex; - justify-content: space-between; - gap: 50px; +.example table tbody tr { + counter-increment: row-counter; } +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; +} + +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -88,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/basic-operations/example1.css b/docs/examples/basic-operations/example1.css index 485d3648f1..2f9f5d066c 100644 --- a/docs/examples/basic-operations/example1.css +++ b/docs/examples/basic-operations/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,131 +39,81 @@ color: #1c49e4; } -.example table { - table-layout: fixed; -} +/* labels */ -.example table tbody tr td, -.example table tbody tr th { - overflow: hidden; - text-overflow: ellipsis; -} - -.example table tbody tr td:first-child span { - width: 100%; +.example label { display: inline-block; - text-align: left; - padding-left: 15px; - margin-left: 0; -} - -.example table tbody tr { - counter-increment: row-counter; + margin-left: 5px; } -.example table tbody tr td:first-child span::before { - content: counter(row-counter); - display: inline-block; - width: 20px; - position: relative; - left: -10px; - font-weight: bold; -} +/* table */ -.example table tbody tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; +.example table { + table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; } -.example table thead tr th:first-child { - padding-left: 40px; +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; } -.example table thead tr th { - counter-increment: col-counter; -} +/* table: header row */ -.example table thead tr th::before { +.example table thead tr th span::before { content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example .crud-entry { - margin-bottom: 10px; -} - -.example #inputs input:focus, -.example #inputs select:focus, -.example #toolbar select:focus { - border-color: #1c49e4; -} - -.example input.inline, -.example select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example input::placeholder { - opacity: 0.55; -} - -.example button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #error-message { - display: none; +.example table thead tr th span { + counter-increment: col-counter; } -.example #disclaimer { - font-size: 1rem; - opacity: 0.6; - margin: 0; -} +/* table: first column */ -.example input:disabled { - background-color: #f7f7f7; +.example table tbody tr td:first-child { + text-align: center; + padding: 0; } -.example #sheet-select { - width: 12rem; +.example table thead tr th:first-child { + padding-left: 40px; } -.example #action-select { - width: 14rem; +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; } -.example #preview-header { - margin: 30px 0 0 0; +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; } -.example #inputs { - display: none; +.example table tbody tr { + counter-increment: row-counter; } -.example #inputs.error input { - border: 1px solid red; -} +/* table: summary row */ -.example #error-message { - color: red; +table tbody tr:last-child { + font-weight: 600; } +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -169,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/basic-usage/example1.css b/docs/examples/basic-usage/example1.css index b709196967..2f9f5d066c 100644 --- a/docs/examples/basic-usage/example1.css +++ b/docs/examples/basic-usage/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,19 +39,48 @@ color: #1c49e4; } -.example table tbody tr td:first-child { - text-align: center; - padding: 0; +/* labels */ + +.example label { + display: inline-block; + margin-left: 5px; } +/* table */ + .example table { table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; } -.example table tbody tr td, -.example table tbody tr th { +.example table tr td, +.example table tr th { overflow: hidden; text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + +/* table: first column */ + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; } .example table thead tr th:first-child { @@ -63,10 +95,6 @@ margin-left: 0; } -.example table tbody tr { - counter-increment: row-counter; -} - .example table tbody tr td:first-child span::before { content: counter(row-counter); display: inline-block; @@ -75,25 +103,27 @@ left: -10px; } -.example table thead tr th span { - counter-increment: col-counter; +.example table tbody tr { + counter-increment: row-counter; } -.example table thead tr th span::before { - content: counter(col-counter, upper-alpha); - display: inline-block; - width: 20px; -} +/* table: summary row */ -.example #address-preview { - font-weight: bold; +table tbody tr:last-child { + font-weight: 600; } -.example div.result { - display: inline-block; - margin: 0 0 0 15px; +/* keyframes animation */ +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } } -.example p.data-label { - margin: 0; -} +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/batch-operations/example1.css b/docs/examples/batch-operations/example1.css index f72f0ce758..2f9f5d066c 100644 --- a/docs/examples/batch-operations/example1.css +++ b/docs/examples/batch-operations/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,38 +39,50 @@ color: #1c49e4; } +/* labels */ + .example label { display: inline-block; margin-left: 5px; } -.example table tbody tr { - counter-increment: row-counter; +/* table */ + +.example table { + table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; +} + +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; } .example table thead tr th span { counter-increment: col-counter; } -.example table tbody tr:last-child { - font-weight: 600; -} +/* table: first column */ .example table tbody tr td:first-child { text-align: center; padding: 0; } -.example table { - table-layout: fixed; -} - -.example table tbody tr td, -.example table tbody tr th { - overflow: hidden; - text-overflow: ellipsis; -} - .example table thead tr th:first-child { padding-left: 40px; } @@ -88,11 +103,17 @@ left: -10px; } -.example table tbody tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; +.example table tbody tr { + counter-increment: row-counter; +} + +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; } +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -101,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/clipboard-operations/example1.css b/docs/examples/clipboard-operations/example1.css index 894f36f33e..2f9f5d066c 100644 --- a/docs/examples/clipboard-operations/example1.css +++ b/docs/examples/clipboard-operations/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,35 +39,50 @@ color: #1c49e4; } +/* labels */ + .example label { display: inline-block; margin-left: 5px; } -.example table tbody tr { - counter-increment: row-counter; +/* table */ + +.example table { + table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; +} + +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; } .example table thead tr th span { counter-increment: col-counter; } +/* table: first column */ .example table tbody tr td:first-child { text-align: center; padding: 0; } -.example table { - table-layout: fixed; -} - -.example table tbody tr td, -.example table tbody tr th { - overflow: hidden; - text-overflow: ellipsis; -} - .example table thead tr th:first-child { padding-left: 40px; } @@ -85,11 +103,17 @@ left: -10px; } -.example table tbody tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; +.example table tbody tr { + counter-increment: row-counter; +} + +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; } +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -98,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/date-time/example1.css b/docs/examples/date-time/example1.css index 210cf4dd73..2f9f5d066c 100644 --- a/docs/examples/date-time/example1.css +++ b/docs/examples/date-time/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,34 +39,50 @@ color: #1c49e4; } +/* labels */ + .example label { display: inline-block; margin-left: 5px; } -.example table tbody tr { - counter-increment: row-counter; +/* table */ + +.example table { + table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; +} + +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; } .example table thead tr th span { counter-increment: col-counter; } +/* table: first column */ + .example table tbody tr td:first-child { text-align: center; padding: 0; } -.example table { - table-layout: fixed; -} - -.example table tbody tr td, -.example table tbody tr th { - overflow: hidden; - text-overflow: ellipsis; -} - .example table thead tr th:first-child { padding-left: 40px; } @@ -84,11 +103,17 @@ left: -10px; } -.example table tbody tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; +.example table tbody tr { + counter-increment: row-counter; +} + +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; } +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -97,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css index e98e9339f3..2f9f5d066c 100644 --- a/docs/examples/demo/example1.css +++ b/docs/examples/demo/example1.css @@ -1,24 +1,27 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; - font-size: 10px; + font-size: 14px; font-weight: 300; letter-spacing: .01em; line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; - border-radius: .4em; + border-radius: .3em; color: #fff; cursor: pointer; display: inline-block; - font-size: 1.1em; + font-size: .85em; font-weight: 700; - height: 3.8em; + height: 3em; letter-spacing: .1em; - line-height: 3.8em; - padding: 0 3.0em; + line-height: 3em; + padding: 0 3em; text-align: center; text-decoration: none; text-transform: uppercase; @@ -36,19 +39,45 @@ color: #1c49e4; } +/* labels */ + +.example label { + display: inline-block; + margin-left: 5px; +} + +/* table */ + .example table { table-layout: fixed; - font-size: 14px; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; } -.example table tbody tr:last-child { - font-weight: 600; +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; } -.example table tbody tr:last-child td:first-child { - text-align: right; +.example table thead tr th span { + counter-increment: col-counter; } +/* table: first column */ + .example table tbody tr td:first-child { text-align: center; padding: 0; @@ -67,7 +96,6 @@ } .example table tbody tr td:first-child span::before { - counter-increment: row-counter; content: counter(row-counter); display: inline-block; width: 20px; @@ -75,11 +103,17 @@ left: -10px; } -.example table tbody tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; +.example table tbody tr { + counter-increment: row-counter; +} + +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; } +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -88,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/example1.css b/docs/examples/example1.css new file mode 100644 index 0000000000..2f9f5d066c --- /dev/null +++ b/docs/examples/example1.css @@ -0,0 +1,129 @@ +/* general */ +.example { + color: #606c76; + font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + font-weight: 300; + letter-spacing: .01em; + line-height: 1.6; +} + +/* buttons */ + +.example button { + border: 0.1em solid #1c49e4; + border-radius: .3em; + color: #fff; + cursor: pointer; + display: inline-block; + font-size: .85em; + font-weight: 700; + height: 3em; + letter-spacing: .1em; + line-height: 3em; + padding: 0 3em; + text-align: center; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + margin-bottom: 20px; + background-color: #1c49e4; +} + +.example button:hover { + background-color: #2350ea; +} + +.example button.outline { + background-color: transparent; + color: #1c49e4; +} + +/* labels */ + +.example label { + display: inline-block; + margin-left: 5px; +} + +/* table */ + +.example table { + table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; +} + +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; +} + +.example table thead tr th span { + counter-increment: col-counter; +} + +/* table: first column */ + +.example table tbody tr td:first-child { + text-align: center; + padding: 0; +} + +.example table thead tr th:first-child { + padding-left: 40px; +} + +.example table tbody tr td:first-child span { + width: 100%; + display: inline-block; + text-align: left; + padding-left: 15px; + margin-left: 0; +} + +.example table tbody tr td:first-child span::before { + content: counter(row-counter); + display: inline-block; + width: 20px; + position: relative; + left: -10px; +} + +.example table tbody tr { + counter-increment: row-counter; +} + +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; +} + +/* keyframes animation */ +@keyframes cell-appear { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/i18n/example1.css b/docs/examples/i18n/example1.css index 61fd054434..2f9f5d066c 100644 --- a/docs/examples/i18n/example1.css +++ b/docs/examples/i18n/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,37 +39,50 @@ color: #1c49e4; } +/* labels */ + .example label { display: inline-block; margin-left: 5px; } -.example table tbody tr { - counter-increment: row-counter; +/* table */ + +.example table { + table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; } -.example table thead tr th span { - counter-increment: col-counter; +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; } -.example table tbody tr:last-child { - font-weight: 600; +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; } -.example table tbody tr:last-child td:first-child { - text-align: right; +.example table thead tr th span { + counter-increment: col-counter; } +/* table: first column */ + .example table tbody tr td:first-child { text-align: center; padding: 0; } -.example table { - table-layout: fixed; - font-size: 14px; -} - .example table thead tr th:first-child { padding-left: 40px; } @@ -87,11 +103,17 @@ left: -10px; } -.example table tbody tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; +.example table tbody tr { + counter-increment: row-counter; } +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; +} + +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -100,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/localizing-functions/example1.css b/docs/examples/localizing-functions/example1.css index f72f0ce758..2f9f5d066c 100644 --- a/docs/examples/localizing-functions/example1.css +++ b/docs/examples/localizing-functions/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,38 +39,50 @@ color: #1c49e4; } +/* labels */ + .example label { display: inline-block; margin-left: 5px; } -.example table tbody tr { - counter-increment: row-counter; +/* table */ + +.example table { + table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; +} + +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; } .example table thead tr th span { counter-increment: col-counter; } -.example table tbody tr:last-child { - font-weight: 600; -} +/* table: first column */ .example table tbody tr td:first-child { text-align: center; padding: 0; } -.example table { - table-layout: fixed; -} - -.example table tbody tr td, -.example table tbody tr th { - overflow: hidden; - text-overflow: ellipsis; -} - .example table thead tr th:first-child { padding-left: 40px; } @@ -88,11 +103,17 @@ left: -10px; } -.example table tbody tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; +.example table tbody tr { + counter-increment: row-counter; +} + +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; } +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -101,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/named-expressions/example1.css b/docs/examples/named-expressions/example1.css index 4960e9d283..2f9f5d066c 100644 --- a/docs/examples/named-expressions/example1.css +++ b/docs/examples/named-expressions/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,40 +39,50 @@ color: #1c49e4; } +/* labels */ + .example label { display: inline-block; margin-left: 5px; } -.example table tbody tr { - counter-increment: row-counter; +/* table */ + +.example table { + table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; +} + +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; } .example table thead tr th span { counter-increment: col-counter; } -.example table tbody tr:nth-child(4), -.example table tbody tr:nth-child(5) { - font-weight: 600; -} +/* table: first column */ .example table tbody tr td:first-child { text-align: center; padding: 0; } -.example table { - table-layout: fixed; -} - -.example table tbody tr td, -.example table tbody tr th { - overflow: hidden; - text-overflow: ellipsis; - word-break: break-all; -} - .example table thead tr th:first-child { padding-left: 40px; } @@ -90,11 +103,17 @@ left: -10px; } -.example table tbody tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; +.example table tbody tr { + counter-increment: row-counter; +} + +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; } +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -103,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/sorting-data/example1.css b/docs/examples/sorting-data/example1.css index 894f36f33e..2f9f5d066c 100644 --- a/docs/examples/sorting-data/example1.css +++ b/docs/examples/sorting-data/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,35 +39,50 @@ color: #1c49e4; } +/* labels */ + .example label { display: inline-block; margin-left: 5px; } -.example table tbody tr { - counter-increment: row-counter; +/* table */ + +.example table { + table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; +} + +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; } .example table thead tr th span { counter-increment: col-counter; } +/* table: first column */ .example table tbody tr td:first-child { text-align: center; padding: 0; } -.example table { - table-layout: fixed; -} - -.example table tbody tr td, -.example table tbody tr th { - overflow: hidden; - text-overflow: ellipsis; -} - .example table thead tr th:first-child { padding-left: 40px; } @@ -85,11 +103,17 @@ left: -10px; } -.example table tbody tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; +.example table tbody tr { + counter-increment: row-counter; +} + +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; } +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -98,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ diff --git a/docs/examples/undo-redo/example1.css b/docs/examples/undo-redo/example1.css index 4b5baea84c..2f9f5d066c 100644 --- a/docs/examples/undo-redo/example1.css +++ b/docs/examples/undo-redo/example1.css @@ -1,3 +1,4 @@ +/* general */ .example { color: #606c76; font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; @@ -7,6 +8,8 @@ line-height: 1.6; } +/* buttons */ + .example button { border: 0.1em solid #1c49e4; border-radius: .3em; @@ -36,28 +39,50 @@ color: #1c49e4; } +/* labels */ + .example label { display: inline-block; margin-left: 5px; } -.example table tbody tr { - counter-increment: row-counter; +/* table */ + +.example table { + table-layout: fixed; + border-spacing: 0; + overflow-x: auto; + text-align: left; + width: 100%; +} + +.example table tr td, +.example table tr th { + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 0.1rem solid #e1e1e1; + padding: .6em 1em; +} + +/* table: header row */ + +.example table thead tr th span::before { + content: counter(col-counter, upper-alpha); + display: inline-block; + width: 20px; } .example table thead tr th span { counter-increment: col-counter; } +/* table: first column */ + .example table tbody tr td:first-child { text-align: center; padding: 0; } -.example table { - table-layout: fixed; -} - .example table thead tr th:first-child { padding-left: 40px; } @@ -78,16 +103,17 @@ left: -10px; } -.example table tbody tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; +.example table tbody tr { + counter-increment: row-counter; } -.example #info-box { - font-size: 1.5rem; - margin-bottom: 10px; +/* table: summary row */ + +table tbody tr:last-child { + font-weight: 600; } +/* keyframes animation */ @keyframes cell-appear { from { opacity: 0; @@ -96,3 +122,8 @@ opacity: 1; } } + +/* TODO: + - dopiescic cssy, + - review adrian, + - krzysiek (instrukcje jak deployowac) */ From 7eb2b034a470c317082cf511bf223633ecc61c56 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 10 Oct 2024 13:44:14 +0200 Subject: [PATCH 32/41] Fix row and column counting in the docs examples --- docs/examples/advanced-usage/example1.css | 13 ++++++++++--- docs/examples/basic-operations/example1.css | 13 ++++++++++--- docs/examples/basic-usage/example1.css | 13 ++++++++++--- docs/examples/basic-usage/example1.html | 2 +- docs/examples/batch-operations/example1.css | 13 ++++++++++--- docs/examples/clipboard-operations/example1.css | 13 ++++++++++--- docs/examples/date-time/example1.css | 13 ++++++++++--- docs/examples/demo/example1.css | 13 ++++++++++--- docs/examples/demo/example1.js | 2 +- docs/examples/demo/example1.ts | 2 +- docs/examples/example1.css | 13 ++++++++++--- docs/examples/i18n/example1.css | 13 ++++++++++--- docs/examples/localizing-functions/example1.css | 13 ++++++++++--- docs/examples/named-expressions/example1.css | 13 ++++++++++--- docs/examples/sorting-data/example1.css | 13 ++++++++++--- docs/examples/undo-redo/example1.css | 13 ++++++++++--- 16 files changed, 133 insertions(+), 42 deletions(-) diff --git a/docs/examples/advanced-usage/example1.css b/docs/examples/advanced-usage/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/advanced-usage/example1.css +++ b/docs/examples/advanced-usage/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/basic-operations/example1.css b/docs/examples/basic-operations/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/basic-operations/example1.css +++ b/docs/examples/basic-operations/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/basic-usage/example1.css b/docs/examples/basic-usage/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/basic-usage/example1.css +++ b/docs/examples/basic-usage/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/basic-usage/example1.html b/docs/examples/basic-usage/example1.html index 1c44e338b7..2489e911ed 100644 --- a/docs/examples/basic-usage/example1.html +++ b/docs/examples/basic-usage/example1.html @@ -6,7 +6,7 @@ result:
- +
diff --git a/docs/examples/batch-operations/example1.css b/docs/examples/batch-operations/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/batch-operations/example1.css +++ b/docs/examples/batch-operations/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/clipboard-operations/example1.css b/docs/examples/clipboard-operations/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/clipboard-operations/example1.css +++ b/docs/examples/clipboard-operations/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/date-time/example1.css b/docs/examples/date-time/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/date-time/example1.css +++ b/docs/examples/date-time/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/demo/example1.css +++ b/docs/examples/demo/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/demo/example1.js b/docs/examples/demo/example1.js index b582ed84d6..04c3cc64c5 100644 --- a/docs/examples/demo/example1.js +++ b/docs/examples/demo/example1.js @@ -98,7 +98,7 @@ function renderTable(calculated = false) { newTbodyHTML += ''; } - totalRowsHTML = ` + totalRowsHTML = `'; } - totalRowsHTML = ` + totalRowsHTML = ``; } - - newTbodyHTML += ''; } tbodyDOM.innerHTML = `${newTbodyHTML}`; diff --git a/docs/examples/basic-usage/example1.ts b/docs/examples/basic-usage/example1.ts index 651ed209ea..5433c7574e 100644 --- a/docs/examples/basic-usage/example1.ts +++ b/docs/examples/basic-usage/example1.ts @@ -61,8 +61,6 @@ function renderTable() { ${cellValue} `; } - - newTbodyHTML += ''; } tbodyDOM.innerHTML = `${newTbodyHTML}`; diff --git a/docs/examples/batch-operations/example1.css b/docs/examples/batch-operations/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/batch-operations/example1.css +++ b/docs/examples/batch-operations/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/clipboard-operations/example1.css b/docs/examples/clipboard-operations/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/clipboard-operations/example1.css +++ b/docs/examples/clipboard-operations/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/date-time/example1.css b/docs/examples/date-time/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/date-time/example1.css +++ b/docs/examples/date-time/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/demo/example1.css +++ b/docs/examples/demo/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/example1.css b/docs/examples/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/example1.css +++ b/docs/examples/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/i18n/example1.css b/docs/examples/i18n/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/i18n/example1.css +++ b/docs/examples/i18n/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/localizing-functions/example1.css b/docs/examples/localizing-functions/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/localizing-functions/example1.css +++ b/docs/examples/localizing-functions/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/named-expressions/example1.css b/docs/examples/named-expressions/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/named-expressions/example1.css +++ b/docs/examples/named-expressions/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/sorting-data/example1.css b/docs/examples/sorting-data/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/sorting-data/example1.css +++ b/docs/examples/sorting-data/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/undo-redo/example1.css b/docs/examples/undo-redo/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/undo-redo/example1.css +++ b/docs/examples/undo-redo/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} From 439af7654c3869b2d28c0e22dd93de02944a0063 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Mon, 14 Oct 2024 12:18:17 +0200 Subject: [PATCH 36/41] Fix styles for batch-operations demo --- docs/examples/basic-operations/example1.html | 8 ++++---- docs/examples/batch-operations/example1.html | 12 ++++++------ docs/examples/batch-operations/example1.js | 2 +- docs/examples/batch-operations/example1.ts | 2 +- docs/examples/clipboard-operations/example1.html | 8 ++++---- docs/examples/localizing-functions/example1.js | 2 +- docs/examples/localizing-functions/example1.ts | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/examples/basic-operations/example1.html b/docs/examples/basic-operations/example1.html index 93f83cfa7f..f009af48ac 100644 --- a/docs/examples/basic-operations/example1.html +++ b/docs/examples/basic-operations/example1.html @@ -1,7 +1,7 @@
-
-
+
+
@@ -19,8 +19,8 @@
-
-
+
+
@@ -9,13 +9,13 @@
-
-
- +
+
+
-
+
TOTAL ${ diff --git a/docs/examples/demo/example1.ts b/docs/examples/demo/example1.ts index 63602fa244..284ed4f8ff 100644 --- a/docs/examples/demo/example1.ts +++ b/docs/examples/demo/example1.ts @@ -100,7 +100,7 @@ function renderTable(calculated = false) { newTbodyHTML += '
TOTAL ${ diff --git a/docs/examples/example1.css b/docs/examples/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/example1.css +++ b/docs/examples/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/i18n/example1.css b/docs/examples/i18n/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/i18n/example1.css +++ b/docs/examples/i18n/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/localizing-functions/example1.css b/docs/examples/localizing-functions/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/localizing-functions/example1.css +++ b/docs/examples/localizing-functions/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/named-expressions/example1.css b/docs/examples/named-expressions/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/named-expressions/example1.css +++ b/docs/examples/named-expressions/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/sorting-data/example1.css b/docs/examples/sorting-data/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/sorting-data/example1.css +++ b/docs/examples/sorting-data/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } diff --git a/docs/examples/undo-redo/example1.css b/docs/examples/undo-redo/example1.css index 2f9f5d066c..2dac93156b 100644 --- a/docs/examples/undo-redo/example1.css +++ b/docs/examples/undo-redo/example1.css @@ -54,6 +54,7 @@ overflow-x: auto; text-align: left; width: 100%; + counter-reset: row-counter col-counter; } .example table tr td, @@ -67,16 +68,22 @@ /* table: header row */ .example table thead tr th span::before { - content: counter(col-counter, upper-alpha); display: inline-block; width: 20px; } -.example table thead tr th span { +.example table.spreadsheet thead tr th span::before { + content: counter(col-counter, upper-alpha); +} + +.example table.spreadsheet thead tr th { counter-increment: col-counter; } /* table: first column */ +.example table.spreadsheet tbody { + counter-set: row-counter -1; +} .example table tbody tr td:first-child { text-align: center; @@ -109,7 +116,7 @@ /* table: summary row */ -table tbody tr:last-child { +table tbody tr.summary { font-weight: 600; } From 46f9de28991109ef0a6296f31687e9c2fe64093e Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 10 Oct 2024 15:34:14 +0200 Subject: [PATCH 33/41] Adjust css of basic-usage demo --- docs/code-examples-generator.sh | 2 +- docs/examples/advanced-usage/example1.css | 28 +++++++++++++++++-- docs/examples/advanced-usage/example1.html | 6 ++-- docs/examples/advanced-usage/example1.js | 4 +-- docs/examples/advanced-usage/example1.ts | 4 +-- docs/examples/basic-operations/example1.css | 28 +++++++++++++++++-- docs/examples/basic-usage/example1.css | 28 +++++++++++++++++-- docs/examples/basic-usage/example1.html | 5 ++-- docs/examples/basic-usage/example1.js | 4 +-- docs/examples/basic-usage/example1.ts | 4 +-- docs/examples/batch-operations/example1.css | 28 +++++++++++++++++-- .../clipboard-operations/example1.css | 28 +++++++++++++++++-- docs/examples/date-time/example1.css | 28 +++++++++++++++++-- docs/examples/demo/example1.css | 28 +++++++++++++++++-- docs/examples/example1.css | 28 +++++++++++++++++-- docs/examples/i18n/example1.css | 28 +++++++++++++++++-- .../localizing-functions/example1.css | 28 +++++++++++++++++-- docs/examples/named-expressions/example1.css | 28 +++++++++++++++++-- docs/examples/sorting-data/example1.css | 28 +++++++++++++++++-- docs/examples/undo-redo/example1.css | 28 +++++++++++++++++-- 20 files changed, 339 insertions(+), 54 deletions(-) diff --git a/docs/code-examples-generator.sh b/docs/code-examples-generator.sh index ecd1da3adc..e9e36c492b 100644 --- a/docs/code-examples-generator.sh +++ b/docs/code-examples-generator.sh @@ -90,7 +90,7 @@ go_through_all_examples_concurrently() { wait echo "Waiting for the result of all jobs..." - sleep 20 + sleep 30 echo "All jobs finished" } diff --git a/docs/examples/advanced-usage/example1.css b/docs/examples/advanced-usage/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/advanced-usage/example1.css +++ b/docs/examples/advanced-usage/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/advanced-usage/example1.html b/docs/examples/advanced-usage/example1.html index a0bad7f6dc..19c97aab69 100644 --- a/docs/examples/advanced-usage/example1.html +++ b/docs/examples/advanced-usage/example1.html @@ -2,9 +2,9 @@ -
- 🏆 - +
+ 🏆 +
diff --git a/docs/examples/advanced-usage/example1.js b/docs/examples/advanced-usage/example1.js index a02c7d20e8..38ae4e3dd8 100644 --- a/docs/examples/advanced-usage/example1.js +++ b/docs/examples/advanced-usage/example1.js @@ -95,10 +95,10 @@ function renderTable(sheetName) { } /** - * Render the result block. + * Render the result block */ function renderResult() { - const resultOutputDOM = document.querySelector('.example #result .output'); + const resultOutputDOM = document.querySelector('.example #output'); const cellAddress = hf.simpleCellAddressFromString( `${sheetInfo.formulas.sheetName}!A1`, hf.getSheetId(sheetInfo.formulas.sheetName) diff --git a/docs/examples/advanced-usage/example1.ts b/docs/examples/advanced-usage/example1.ts index 8b7b01d519..3dbd8ef2e3 100644 --- a/docs/examples/advanced-usage/example1.ts +++ b/docs/examples/advanced-usage/example1.ts @@ -97,10 +97,10 @@ function renderTable(sheetName) { } /** - * Render the result block. + * Render the result block */ function renderResult() { - const resultOutputDOM = document.querySelector('.example #result .output'); + const resultOutputDOM = document.querySelector('.example #output'); const cellAddress = hf.simpleCellAddressFromString( `${sheetInfo.formulas.sheetName}!A1`, hf.getSheetId(sheetInfo.formulas.sheetName) diff --git a/docs/examples/basic-operations/example1.css b/docs/examples/basic-operations/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/basic-operations/example1.css +++ b/docs/examples/basic-operations/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/basic-usage/example1.css b/docs/examples/basic-usage/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/basic-usage/example1.css +++ b/docs/examples/basic-usage/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/basic-usage/example1.html b/docs/examples/basic-usage/example1.html index 2489e911ed..df9c6a2a33 100644 --- a/docs/examples/basic-usage/example1.html +++ b/docs/examples/basic-usage/example1.html @@ -2,9 +2,8 @@ -
- result: - +
+ result:
diff --git a/docs/examples/basic-usage/example1.js b/docs/examples/basic-usage/example1.js index 8b426855d2..ca9187c3ff 100644 --- a/docs/examples/basic-usage/example1.js +++ b/docs/examples/basic-usage/example1.js @@ -73,8 +73,8 @@ function renderTable() { */ function bindEvents() { const calculateButton = document.querySelector('.example #calculate'); - const formulaPreview = document.querySelector('.example #address-preview'); - const calculationResult = document.querySelector('.example #result'); + const formulaPreview = document.querySelector('.example #address-output'); + const calculationResult = document.querySelector('.example #result-output'); const cellAddress = { sheet: sheetId, row: 0, col: 2 }; formulaPreview.innerText = hf.simpleCellAddressToString(cellAddress, sheetId); diff --git a/docs/examples/basic-usage/example1.ts b/docs/examples/basic-usage/example1.ts index d256f3d2a0..651ed209ea 100644 --- a/docs/examples/basic-usage/example1.ts +++ b/docs/examples/basic-usage/example1.ts @@ -74,8 +74,8 @@ function renderTable() { */ function bindEvents() { const calculateButton = document.querySelector('.example #calculate'); - const formulaPreview = document.querySelector('.example #address-preview'); - const calculationResult = document.querySelector('.example #result'); + const formulaPreview = document.querySelector('.example #address-output'); + const calculationResult = document.querySelector('.example #result-output'); const cellAddress = { sheet: sheetId, row: 0, col: 2 }; formulaPreview.innerText = hf.simpleCellAddressToString(cellAddress, sheetId); diff --git a/docs/examples/batch-operations/example1.css b/docs/examples/batch-operations/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/batch-operations/example1.css +++ b/docs/examples/batch-operations/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/clipboard-operations/example1.css b/docs/examples/clipboard-operations/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/clipboard-operations/example1.css +++ b/docs/examples/clipboard-operations/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/date-time/example1.css b/docs/examples/date-time/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/date-time/example1.css +++ b/docs/examples/date-time/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/demo/example1.css +++ b/docs/examples/demo/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/example1.css b/docs/examples/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/example1.css +++ b/docs/examples/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/i18n/example1.css b/docs/examples/i18n/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/i18n/example1.css +++ b/docs/examples/i18n/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/localizing-functions/example1.css b/docs/examples/localizing-functions/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/localizing-functions/example1.css +++ b/docs/examples/localizing-functions/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/named-expressions/example1.css b/docs/examples/named-expressions/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/named-expressions/example1.css +++ b/docs/examples/named-expressions/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/sorting-data/example1.css b/docs/examples/sorting-data/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/sorting-data/example1.css +++ b/docs/examples/sorting-data/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; diff --git a/docs/examples/undo-redo/example1.css b/docs/examples/undo-redo/example1.css index 2dac93156b..824e181fc0 100644 --- a/docs/examples/undo-redo/example1.css +++ b/docs/examples/undo-redo/example1.css @@ -1,7 +1,7 @@ /* general */ .example { color: #606c76; - font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-family: sans-serif; font-size: 14px; font-weight: 300; letter-spacing: .01em; @@ -17,6 +17,7 @@ cursor: pointer; display: inline-block; font-size: .85em; + font-family: inherit; font-weight: 700; height: 3em; letter-spacing: .1em; @@ -46,6 +47,21 @@ margin-left: 5px; } +/* message */ + +.message-box { + border: 1px solid #1c49e433; + background-color: #1c49e405; + border-radius: 0.2rem; + padding: 10px; +} + +.message-box span { + animation-name: cell-appear; + animation-duration: 0.2s; + margin: 0; +} + /* table */ .example table { @@ -116,11 +132,17 @@ /* table: summary row */ -table tbody tr.summary { +.example table tbody tr.summary { font-weight: 600; } -/* keyframes animation */ +/* updated-cell animation */ + +.example table tr td.updated-cell span { + animation-name: cell-appear; + animation-duration: 0.6s; +} + @keyframes cell-appear { from { opacity: 0; From af0d548e4c10ff06fda4b6685100e79cfcb70b51 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Thu, 10 Oct 2024 15:51:13 +0200 Subject: [PATCH 34/41] Adjust style of advanced-usage demo --- docs/examples/advanced-usage/example1.html | 24 +++++++++------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/docs/examples/advanced-usage/example1.html b/docs/examples/advanced-usage/example1.html index 19c97aab69..2973be171d 100644 --- a/docs/examples/advanced-usage/example1.html +++ b/docs/examples/advanced-usage/example1.html @@ -6,10 +6,9 @@ 🏆 -
-
-
-

Team A

+
+
+

Team A

@@ -24,8 +23,8 @@

Team A

-
-

Team B

+
+

Team B

@@ -40,14 +39,11 @@

Team B

-
-
-
-

Formulas

- - -
-
+
+

Formulas

+ + +
\ No newline at end of file From ba6fefb15b6653856ebf9c907220ab8316ba6107 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Mon, 14 Oct 2024 12:05:43 +0200 Subject: [PATCH 35/41] Fix styles for basic-operations demo --- docs/examples/advanced-usage/example1.css | 86 +++++++++++++++++-- docs/examples/basic-operations/example1.css | 86 +++++++++++++++++-- docs/examples/basic-operations/example1.html | 29 ++++--- docs/examples/basic-operations/example1.js | 4 +- docs/examples/basic-operations/example1.ts | 4 +- docs/examples/basic-usage/example1.css | 86 +++++++++++++++++-- docs/examples/basic-usage/example1.js | 2 - docs/examples/basic-usage/example1.ts | 2 - docs/examples/batch-operations/example1.css | 86 +++++++++++++++++-- .../clipboard-operations/example1.css | 86 +++++++++++++++++-- docs/examples/date-time/example1.css | 86 +++++++++++++++++-- docs/examples/demo/example1.css | 86 +++++++++++++++++-- docs/examples/example1.css | 86 +++++++++++++++++-- docs/examples/i18n/example1.css | 86 +++++++++++++++++-- .../localizing-functions/example1.css | 86 +++++++++++++++++-- docs/examples/named-expressions/example1.css | 86 +++++++++++++++++-- docs/examples/sorting-data/example1.css | 86 +++++++++++++++++-- docs/examples/undo-redo/example1.css | 86 +++++++++++++++++-- 18 files changed, 1050 insertions(+), 109 deletions(-) diff --git a/docs/examples/advanced-usage/example1.css b/docs/examples/advanced-usage/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/advanced-usage/example1.css +++ b/docs/examples/advanced-usage/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/basic-operations/example1.css b/docs/examples/basic-operations/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/basic-operations/example1.css +++ b/docs/examples/basic-operations/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/basic-operations/example1.html b/docs/examples/basic-operations/example1.html index 30f3757829..93f83cfa7f 100644 --- a/docs/examples/basic-operations/example1.html +++ b/docs/examples/basic-operations/example1.html @@ -26,21 +26,30 @@ -

-

+
+

+

+
- +
+ + + + + + + - - - - - - - + + + + + + +
diff --git a/docs/examples/basic-operations/example1.js b/docs/examples/basic-operations/example1.js index 6f094daee5..41f5d2e6f6 100644 --- a/docs/examples/basic-operations/example1.js +++ b/docs/examples/basic-operations/example1.js @@ -272,7 +272,7 @@ function renderError(message) { } errorDOM.innerText = message; - errorDOM.style.display = 'block'; + errorDOM.parentElement.style.display = 'block'; } /** @@ -284,7 +284,7 @@ function clearError() { inputsDOM.className = inputsDOM.className.replace(' error', ''); errorDOM.innerText = ''; - errorDOM.style.display = 'none'; + errorDOM.parentElement.style.display = 'none'; } /** diff --git a/docs/examples/basic-operations/example1.ts b/docs/examples/basic-operations/example1.ts index af05a4c77b..74c22d830c 100644 --- a/docs/examples/basic-operations/example1.ts +++ b/docs/examples/basic-operations/example1.ts @@ -276,7 +276,7 @@ function renderError(message) { } errorDOM.innerText = message; - errorDOM.style.display = 'block'; + errorDOM.parentElement.style.display = 'block'; } /** @@ -289,7 +289,7 @@ function clearError() { inputsDOM.className = inputsDOM.className.replace(' error', ''); errorDOM.innerText = ''; - errorDOM.style.display = 'none'; + errorDOM.parentElement.style.display = 'none'; } /** diff --git a/docs/examples/basic-usage/example1.css b/docs/examples/basic-usage/example1.css index 824e181fc0..48c574f790 100644 --- a/docs/examples/basic-usage/example1.css +++ b/docs/examples/basic-usage/example1.css @@ -6,6 +6,15 @@ font-weight: 300; letter-spacing: .01em; line-height: 1.6; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.example *, +.example *::before, +.example *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; } /* buttons */ @@ -47,6 +56,26 @@ margin-left: 5px; } +/* inputs */ + +.example input, .example select, .example textarea, .example fieldset { + margin-bottom: 1.5em; + border: 0.1em solid #d1d1d1; + border-radius: .4em; + height: 3.8em; + padding: .6em 1em .7em; +} + +.example select { + padding-right: 3em; +} + +.example input:focus, +.example select:focus { + outline: none; + border-color: #1c49e4; +} + /* message */ .message-box { @@ -73,6 +102,10 @@ counter-reset: row-counter col-counter; } +.example table tr:nth-child(2n) { + background-color: #f6f8fa; +} + .example table tr td, .example table tr th { overflow: hidden; @@ -97,9 +130,6 @@ } /* table: first column */ -.example table.spreadsheet tbody { - counter-set: row-counter -1; -} .example table tbody tr td:first-child { text-align: center; @@ -152,7 +182,49 @@ } } -/* TODO: - - dopiescic cssy, - - review adrian, - - krzysiek (instrukcje jak deployowac) */ +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/basic-usage/example1.js b/docs/examples/basic-usage/example1.js index ca9187c3ff..05fce6bdde 100644 --- a/docs/examples/basic-usage/example1.js +++ b/docs/examples/basic-usage/example1.js @@ -60,8 +60,6 @@ function renderTable() { ${cellValue}
diff --git a/docs/examples/batch-operations/example1.js b/docs/examples/batch-operations/example1.js index 4daa2bfce9..4fe6e426c7 100644 --- a/docs/examples/batch-operations/example1.js +++ b/docs/examples/batch-operations/example1.js @@ -88,7 +88,7 @@ function renderTable(calculated = false) { newTbodyHTML += ''; } - totalRowsHTML = ` + totalRowsHTML = `'; } - totalRowsHTML = ` + totalRowsHTML = `'; } - totalRowsHTML = ` + totalRowsHTML = `'; } - totalRowsHTML = ` + totalRowsHTML = ` From 30adad30eea4296af4284c32b5e87060c61d1037 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Tue, 15 Oct 2024 11:58:31 +0200 Subject: [PATCH 38/41] Fix height of the table cell in the demos --- docs/examples/advanced-usage/example1.css | 7 ++++--- docs/examples/basic-operations/example1.css | 7 ++++--- docs/examples/basic-usage/example1.css | 7 ++++--- docs/examples/batch-operations/example1.css | 7 ++++--- docs/examples/clipboard-operations/example1.css | 7 ++++--- docs/examples/date-time/example1.css | 7 ++++--- docs/examples/demo/example1.css | 7 ++++--- docs/examples/example1.css | 7 ++++--- docs/examples/i18n/example1.css | 7 ++++--- docs/examples/localizing-functions/example1.css | 7 ++++--- docs/examples/named-expressions/example1.css | 7 ++++--- docs/examples/sorting-data/example1.css | 7 ++++--- docs/examples/undo-redo/example1.css | 7 ++++--- 13 files changed, 52 insertions(+), 39 deletions(-) diff --git a/docs/examples/advanced-usage/example1.css b/docs/examples/advanced-usage/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/advanced-usage/example1.css +++ b/docs/examples/advanced-usage/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/basic-operations/example1.css b/docs/examples/basic-operations/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/basic-operations/example1.css +++ b/docs/examples/basic-operations/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/basic-usage/example1.css b/docs/examples/basic-usage/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/basic-usage/example1.css +++ b/docs/examples/basic-usage/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/batch-operations/example1.css b/docs/examples/batch-operations/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/batch-operations/example1.css +++ b/docs/examples/batch-operations/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/clipboard-operations/example1.css b/docs/examples/clipboard-operations/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/clipboard-operations/example1.css +++ b/docs/examples/clipboard-operations/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/date-time/example1.css b/docs/examples/date-time/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/date-time/example1.css +++ b/docs/examples/date-time/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/demo/example1.css +++ b/docs/examples/demo/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/example1.css b/docs/examples/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/example1.css +++ b/docs/examples/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/i18n/example1.css b/docs/examples/i18n/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/i18n/example1.css +++ b/docs/examples/i18n/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/localizing-functions/example1.css b/docs/examples/localizing-functions/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/localizing-functions/example1.css +++ b/docs/examples/localizing-functions/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/named-expressions/example1.css b/docs/examples/named-expressions/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/named-expressions/example1.css +++ b/docs/examples/named-expressions/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/sorting-data/example1.css b/docs/examples/sorting-data/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/sorting-data/example1.css +++ b/docs/examples/sorting-data/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ diff --git a/docs/examples/undo-redo/example1.css b/docs/examples/undo-redo/example1.css index 48c574f790..f8107a43a8 100644 --- a/docs/examples/undo-redo/example1.css +++ b/docs/examples/undo-redo/example1.css @@ -81,7 +81,7 @@ .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; - border-radius: 0.2rem; + border-radius: 0.2em; padding: 10px; } @@ -110,8 +110,9 @@ .example table tr th { overflow: hidden; text-overflow: ellipsis; - border-bottom: 0.1rem solid #e1e1e1; - padding: .6em 1em; + border-bottom: 0.1em solid #e1e1e1; + padding: 0 1em; + height: 3.5em; } /* table: header row */ From fbbb10b97a4c8a658722fa9f3fcc7a287805ba36 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Tue, 15 Oct 2024 12:15:21 +0200 Subject: [PATCH 39/41] Adjust text decoration of the summary row in the i18n demo --- docs/examples/advanced-usage/example1.css | 49 +------------------ docs/examples/basic-operations/example1.css | 49 +------------------ docs/examples/basic-usage/example1.css | 49 +------------------ docs/examples/batch-operations/example1.css | 2 +- .../clipboard-operations/example1.css | 49 +------------------ docs/examples/date-time/example1.css | 49 +------------------ docs/examples/demo/example1.css | 49 +------------------ docs/examples/example1.css | 49 +------------------ docs/examples/i18n/example1.css | 49 +------------------ docs/examples/i18n/example1.js | 6 +-- docs/examples/i18n/example1.ts | 8 ++- .../localizing-functions/example1.css | 49 +------------------ docs/examples/named-expressions/example1.css | 49 +------------------ docs/examples/sorting-data/example1.css | 49 +------------------ docs/examples/undo-redo/example1.css | 49 +------------------ 15 files changed, 19 insertions(+), 585 deletions(-) diff --git a/docs/examples/advanced-usage/example1.css b/docs/examples/advanced-usage/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/advanced-usage/example1.css +++ b/docs/examples/advanced-usage/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/basic-operations/example1.css b/docs/examples/basic-operations/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/basic-operations/example1.css +++ b/docs/examples/basic-operations/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/basic-usage/example1.css b/docs/examples/basic-usage/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/basic-usage/example1.css +++ b/docs/examples/basic-usage/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/batch-operations/example1.css b/docs/examples/batch-operations/example1.css index f8107a43a8..9c76df6154 100644 --- a/docs/examples/batch-operations/example1.css +++ b/docs/examples/batch-operations/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; diff --git a/docs/examples/clipboard-operations/example1.css b/docs/examples/clipboard-operations/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/clipboard-operations/example1.css +++ b/docs/examples/clipboard-operations/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/date-time/example1.css b/docs/examples/date-time/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/date-time/example1.css +++ b/docs/examples/date-time/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/demo/example1.css +++ b/docs/examples/demo/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/example1.css b/docs/examples/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/example1.css +++ b/docs/examples/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/i18n/example1.css b/docs/examples/i18n/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/i18n/example1.css +++ b/docs/examples/i18n/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/i18n/example1.js b/docs/examples/i18n/example1.js index 89f7d266d2..e48958f3bc 100644 --- a/docs/examples/i18n/example1.js +++ b/docs/examples/i18n/example1.js @@ -155,6 +155,8 @@ function renderTable(calculated = false) { let newTbodyHTML = ''; for (let row = 0; row < height; row++) { + newTbodyHTML += ``; + for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); @@ -165,9 +167,7 @@ function renderTable(calculated = false) { newTbodyHTML += ``; + }">${displayValue}`; } newTbodyHTML += ''; diff --git a/docs/examples/i18n/example1.ts b/docs/examples/i18n/example1.ts index cb6a1b9646..d2aa6bc63c 100644 --- a/docs/examples/i18n/example1.ts +++ b/docs/examples/i18n/example1.ts @@ -157,6 +157,8 @@ function renderTable(calculated = false) { let newTbodyHTML = ''; for (let row = 0; row < height; row++) { + newTbodyHTML += ``; + for (let col = 0; col < width; col++) { const cellAddress = { sheet: sheetId, col, row }; const cellHasFormula = hf.doesCellHaveFormula(cellAddress); @@ -165,11 +167,7 @@ function renderTable(calculated = false) { ? hf.getCellFormula(cellAddress) : formatCellValue(cellAddress); - newTbodyHTML += ``; + newTbodyHTML += ``; } newTbodyHTML += ''; diff --git a/docs/examples/localizing-functions/example1.css b/docs/examples/localizing-functions/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/localizing-functions/example1.css +++ b/docs/examples/localizing-functions/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/named-expressions/example1.css b/docs/examples/named-expressions/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/named-expressions/example1.css +++ b/docs/examples/named-expressions/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/sorting-data/example1.css b/docs/examples/sorting-data/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/sorting-data/example1.css +++ b/docs/examples/sorting-data/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/undo-redo/example1.css b/docs/examples/undo-redo/example1.css index f8107a43a8..32e78f8fa1 100644 --- a/docs/examples/undo-redo/example1.css +++ b/docs/examples/undo-redo/example1.css @@ -85,7 +85,7 @@ padding: 10px; } -.message-box span { +.example .message-box span { animation-name: cell-appear; animation-duration: 0.2s; margin: 0; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} From 19a0f4a569d2c0df2218e39a937aa961541cd5f8 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Tue, 15 Oct 2024 12:31:00 +0200 Subject: [PATCH 40/41] Fix styles for basic-operations demo --- docs/examples/advanced-usage/example1.css | 2 +- docs/examples/basic-operations/example1.css | 49 ++++- docs/examples/basic-operations/example1.js | 2 + docs/examples/basic-operations/example1.ts | 3 + docs/examples/basic-usage/example1.css | 2 +- docs/examples/batch-operations/example1.css | 49 +---- .../clipboard-operations/example1.css | 2 +- docs/examples/date-time/example1.css | 2 +- docs/examples/demo/example1.css | 2 +- docs/examples/example1.css | 184 ------------------ docs/examples/i18n/example1.css | 2 +- .../localizing-functions/example1.css | 2 +- docs/examples/named-expressions/example1.css | 2 +- docs/examples/sorting-data/example1.css | 2 +- docs/examples/undo-redo/example1.css | 2 +- 15 files changed, 64 insertions(+), 243 deletions(-) delete mode 100644 docs/examples/example1.css diff --git a/docs/examples/advanced-usage/example1.css b/docs/examples/advanced-usage/example1.css index 32e78f8fa1..3d17963854 100644 --- a/docs/examples/advanced-usage/example1.css +++ b/docs/examples/advanced-usage/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; diff --git a/docs/examples/basic-operations/example1.css b/docs/examples/basic-operations/example1.css index 32e78f8fa1..de6c136661 100644 --- a/docs/examples/basic-operations/example1.css +++ b/docs/examples/basic-operations/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; @@ -182,3 +182,50 @@ opacity: 1; } } + +/* basic-operations form */ + +.example #inputs { + display: none; +} + +.example #inputs input, +.example #toolbar select, +.example #inputs button { + height: 38px; +} + +.example #inputs input.inline, +.example #inputs select.inline { + border-bottom-right-radius: 0; + border-right: 0; + border-top-right-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs button.inline { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0; +} + +.example #inputs input.inline.middle { + border-radius: 0; + margin: 0; + width: 10em; + float: left; +} + +.example #inputs input::placeholder { + opacity: 0.55; +} + +.example #inputs input:disabled { + background-color: #f7f7f7; +} + +.example #inputs.error input { + border: 1px solid red; +} diff --git a/docs/examples/basic-operations/example1.js b/docs/examples/basic-operations/example1.js index 41f5d2e6f6..e95d0b5396 100644 --- a/docs/examples/basic-operations/example1.js +++ b/docs/examples/basic-operations/example1.js @@ -251,6 +251,7 @@ function updateForm(action) { if (inputConfig[action].disclaimer) { disclaimerDOM.innerHTML = inputConfig[action].disclaimer; + disclaimerDOM.parentElement.style.display = 'block'; } else { disclaimerDOM.innerHTML = ' '; } @@ -457,3 +458,4 @@ bindEvents(); renderTable(); // Refresh the sheet dropdown list updateSheetDropdown(); +document.querySelector('.example .message-box').style.display = 'block'; diff --git a/docs/examples/basic-operations/example1.ts b/docs/examples/basic-operations/example1.ts index 74c22d830c..356bf1f66f 100644 --- a/docs/examples/basic-operations/example1.ts +++ b/docs/examples/basic-operations/example1.ts @@ -255,6 +255,7 @@ function updateForm(action) { if (inputConfig[action].disclaimer) { disclaimerDOM.innerHTML = inputConfig[action].disclaimer; + disclaimerDOM.parentElement.style.display = 'block'; } else { disclaimerDOM.innerHTML = ' '; } @@ -476,3 +477,5 @@ renderTable(); // Refresh the sheet dropdown list updateSheetDropdown(); + +document.querySelector('.example .message-box').style.display = 'block'; diff --git a/docs/examples/basic-usage/example1.css b/docs/examples/basic-usage/example1.css index 32e78f8fa1..3d17963854 100644 --- a/docs/examples/basic-usage/example1.css +++ b/docs/examples/basic-usage/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; diff --git a/docs/examples/batch-operations/example1.css b/docs/examples/batch-operations/example1.css index 9c76df6154..3d17963854 100644 --- a/docs/examples/batch-operations/example1.css +++ b/docs/examples/batch-operations/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; @@ -182,50 +182,3 @@ opacity: 1; } } - -/* basic-operations form */ - -.example #inputs { - display: none; -} - -.example #inputs input, -.example #toolbar select, -.example #inputs button { - height: 38px; -} - -.example #inputs input.inline, -.example #inputs select.inline { - border-bottom-right-radius: 0; - border-right: 0; - border-top-right-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs button.inline { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0; -} - -.example #inputs input.inline.middle { - border-radius: 0; - margin: 0; - width: 10em; - float: left; -} - -.example #inputs input::placeholder { - opacity: 0.55; -} - -.example #inputs input:disabled { - background-color: #f7f7f7; -} - -.example #inputs.error input { - border: 1px solid red; -} diff --git a/docs/examples/clipboard-operations/example1.css b/docs/examples/clipboard-operations/example1.css index 32e78f8fa1..3d17963854 100644 --- a/docs/examples/clipboard-operations/example1.css +++ b/docs/examples/clipboard-operations/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; diff --git a/docs/examples/date-time/example1.css b/docs/examples/date-time/example1.css index 32e78f8fa1..3d17963854 100644 --- a/docs/examples/date-time/example1.css +++ b/docs/examples/date-time/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css index 32e78f8fa1..3d17963854 100644 --- a/docs/examples/demo/example1.css +++ b/docs/examples/demo/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; diff --git a/docs/examples/example1.css b/docs/examples/example1.css deleted file mode 100644 index 32e78f8fa1..0000000000 --- a/docs/examples/example1.css +++ /dev/null @@ -1,184 +0,0 @@ -/* general */ -.example { - color: #606c76; - font-family: sans-serif; - font-size: 14px; - font-weight: 300; - letter-spacing: .01em; - line-height: 1.6; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -.example *, -.example *::before, -.example *::after { - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -/* buttons */ - -.example button { - border: 0.1em solid #1c49e4; - border-radius: .3em; - color: #fff; - cursor: pointer; - display: inline-block; - font-size: .85em; - font-family: inherit; - font-weight: 700; - height: 3em; - letter-spacing: .1em; - line-height: 3em; - padding: 0 3em; - text-align: center; - text-decoration: none; - text-transform: uppercase; - white-space: nowrap; - margin-bottom: 20px; - background-color: #1c49e4; -} - -.example button:hover { - background-color: #2350ea; -} - -.example button.outline { - background-color: transparent; - color: #1c49e4; -} - -/* labels */ - -.example label { - display: inline-block; - margin-left: 5px; -} - -/* inputs */ - -.example input, .example select, .example textarea, .example fieldset { - margin-bottom: 1.5em; - border: 0.1em solid #d1d1d1; - border-radius: .4em; - height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; -} - -.example input:focus, -.example select:focus { - outline: none; - border-color: #1c49e4; -} - -/* message */ - -.message-box { - border: 1px solid #1c49e433; - background-color: #1c49e405; - border-radius: 0.2em; - padding: 10px; -} - -.example .message-box span { - animation-name: cell-appear; - animation-duration: 0.2s; - margin: 0; -} - -/* table */ - -.example table { - table-layout: fixed; - border-spacing: 0; - overflow-x: auto; - text-align: left; - width: 100%; - counter-reset: row-counter col-counter; -} - -.example table tr:nth-child(2n) { - background-color: #f6f8fa; -} - -.example table tr td, -.example table tr th { - overflow: hidden; - text-overflow: ellipsis; - border-bottom: 0.1em solid #e1e1e1; - padding: 0 1em; - height: 3.5em; -} - -/* table: header row */ - -.example table thead tr th span::before { - display: inline-block; - width: 20px; -} - -.example table.spreadsheet thead tr th span::before { - content: counter(col-counter, upper-alpha); -} - -.example table.spreadsheet thead tr th { - counter-increment: col-counter; -} - -/* table: first column */ - -.example table tbody tr td:first-child { - text-align: center; - padding: 0; -} - -.example table thead tr th:first-child { - padding-left: 40px; -} - -.example table tbody tr td:first-child span { - width: 100%; - display: inline-block; - text-align: left; - padding-left: 15px; - margin-left: 0; -} - -.example table tbody tr td:first-child span::before { - content: counter(row-counter); - display: inline-block; - width: 20px; - position: relative; - left: -10px; -} - -.example table tbody tr { - counter-increment: row-counter; -} - -/* table: summary row */ - -.example table tbody tr.summary { - font-weight: 600; -} - -/* updated-cell animation */ - -.example table tr td.updated-cell span { - animation-name: cell-appear; - animation-duration: 0.6s; -} - -@keyframes cell-appear { - from { - opacity: 0; - } - to { - opacity: 1; - } -} diff --git a/docs/examples/i18n/example1.css b/docs/examples/i18n/example1.css index 32e78f8fa1..3d17963854 100644 --- a/docs/examples/i18n/example1.css +++ b/docs/examples/i18n/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; diff --git a/docs/examples/localizing-functions/example1.css b/docs/examples/localizing-functions/example1.css index 32e78f8fa1..3d17963854 100644 --- a/docs/examples/localizing-functions/example1.css +++ b/docs/examples/localizing-functions/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; diff --git a/docs/examples/named-expressions/example1.css b/docs/examples/named-expressions/example1.css index 32e78f8fa1..3d17963854 100644 --- a/docs/examples/named-expressions/example1.css +++ b/docs/examples/named-expressions/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; diff --git a/docs/examples/sorting-data/example1.css b/docs/examples/sorting-data/example1.css index 32e78f8fa1..3d17963854 100644 --- a/docs/examples/sorting-data/example1.css +++ b/docs/examples/sorting-data/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; diff --git a/docs/examples/undo-redo/example1.css b/docs/examples/undo-redo/example1.css index 32e78f8fa1..3d17963854 100644 --- a/docs/examples/undo-redo/example1.css +++ b/docs/examples/undo-redo/example1.css @@ -78,7 +78,7 @@ /* message */ -.message-box { +.example .message-box { border: 1px solid #1c49e433; background-color: #1c49e405; border-radius: 0.2em; From 95ff6d73f6c972505d9059a7a0967d96209b0d49 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Wed, 16 Oct 2024 12:06:14 +0200 Subject: [PATCH 41/41] Adjust styles for the inputs --- docs/examples/advanced-usage/example1.css | 7 ++----- docs/examples/basic-operations/example1.css | 7 ++----- docs/examples/basic-usage/example1.css | 7 ++----- docs/examples/batch-operations/example1.css | 7 ++----- docs/examples/clipboard-operations/example1.css | 7 ++----- docs/examples/date-time/example1.css | 7 ++----- docs/examples/demo/example1.css | 7 ++----- docs/examples/i18n/example1.css | 7 ++----- docs/examples/localizing-functions/example1.css | 7 ++----- docs/examples/named-expressions/example1.css | 7 ++----- docs/examples/sorting-data/example1.css | 7 ++----- docs/examples/undo-redo/example1.css | 7 ++----- 12 files changed, 24 insertions(+), 60 deletions(-) diff --git a/docs/examples/advanced-usage/example1.css b/docs/examples/advanced-usage/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/advanced-usage/example1.css +++ b/docs/examples/advanced-usage/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/basic-operations/example1.css b/docs/examples/basic-operations/example1.css index de6c136661..ab02174057 100644 --- a/docs/examples/basic-operations/example1.css +++ b/docs/examples/basic-operations/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/basic-usage/example1.css b/docs/examples/basic-usage/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/basic-usage/example1.css +++ b/docs/examples/basic-usage/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/batch-operations/example1.css b/docs/examples/batch-operations/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/batch-operations/example1.css +++ b/docs/examples/batch-operations/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/clipboard-operations/example1.css b/docs/examples/clipboard-operations/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/clipboard-operations/example1.css +++ b/docs/examples/clipboard-operations/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/date-time/example1.css b/docs/examples/date-time/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/date-time/example1.css +++ b/docs/examples/date-time/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/demo/example1.css b/docs/examples/demo/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/demo/example1.css +++ b/docs/examples/demo/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/i18n/example1.css b/docs/examples/i18n/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/i18n/example1.css +++ b/docs/examples/i18n/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/localizing-functions/example1.css b/docs/examples/localizing-functions/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/localizing-functions/example1.css +++ b/docs/examples/localizing-functions/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/named-expressions/example1.css b/docs/examples/named-expressions/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/named-expressions/example1.css +++ b/docs/examples/named-expressions/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/sorting-data/example1.css b/docs/examples/sorting-data/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/sorting-data/example1.css +++ b/docs/examples/sorting-data/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus, diff --git a/docs/examples/undo-redo/example1.css b/docs/examples/undo-redo/example1.css index 3d17963854..949e18695d 100644 --- a/docs/examples/undo-redo/example1.css +++ b/docs/examples/undo-redo/example1.css @@ -63,11 +63,8 @@ border: 0.1em solid #d1d1d1; border-radius: .4em; height: 3.8em; - padding: .6em 1em .7em; -} - -.example select { - padding-right: 3em; + width: 12em; + padding: 0 .5em; } .example input:focus,
TOTAL ${ diff --git a/docs/examples/batch-operations/example1.ts b/docs/examples/batch-operations/example1.ts index f88140f048..5739189c27 100644 --- a/docs/examples/batch-operations/example1.ts +++ b/docs/examples/batch-operations/example1.ts @@ -89,7 +89,7 @@ function renderTable(calculated = false) { newTbodyHTML += '
TOTAL ${ diff --git a/docs/examples/clipboard-operations/example1.html b/docs/examples/clipboard-operations/example1.html index 13b687946e..ba9e9668bf 100644 --- a/docs/examples/clipboard-operations/example1.html +++ b/docs/examples/clipboard-operations/example1.html @@ -1,6 +1,6 @@
-
-
+
+
@@ -13,8 +13,8 @@
-
-
+
+
diff --git a/docs/examples/localizing-functions/example1.js b/docs/examples/localizing-functions/example1.js index 1bf70fa0ef..06a62f0438 100644 --- a/docs/examples/localizing-functions/example1.js +++ b/docs/examples/localizing-functions/example1.js @@ -94,7 +94,7 @@ function renderTable(calculated = false) { newTbodyHTML += '
TOTAL ${ diff --git a/docs/examples/localizing-functions/example1.ts b/docs/examples/localizing-functions/example1.ts index b6ad79d8b3..f045af9748 100644 --- a/docs/examples/localizing-functions/example1.ts +++ b/docs/examples/localizing-functions/example1.ts @@ -96,7 +96,7 @@ function renderTable(calculated = false) { newTbodyHTML += '
TOTAL ${ From f9e1b37fba8453b4d01c7e071bcdaedef318a5d8 Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Mon, 14 Oct 2024 13:53:00 +0200 Subject: [PATCH 37/41] Fix styles for sorting demo --- docs/examples/sorting-data/example1.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/sorting-data/example1.html b/docs/examples/sorting-data/example1.html index be037f8baf..27eec1da0c 100644 --- a/docs/examples/sorting-data/example1.html +++ b/docs/examples/sorting-data/example1.html @@ -8,8 +8,8 @@
Name - Score - + Score +
- ${displayValue} -
- ${displayValue} - ${displayValue}