From 703ef9e45d2f40a8a1bd0fea50c253809649cf8d Mon Sep 17 00:00:00 2001 From: Ayo Ayco Date: Fri, 8 Dec 2023 13:15:00 +0100 Subject: [PATCH] feat: initial utils distribution (#7) --- package.json | 11 +++++---- src/WebComponent.js | 46 +++++++------------------------------ src/utils/get-camel-case.js | 3 +++ src/utils/get-kebab-case.js | 6 +++++ src/utils/index.js | 1 + src/utils/parse.js | 23 +++++++++++++++++++ tsconfig.json | 15 ++++++++++++ 7 files changed, 63 insertions(+), 42 deletions(-) create mode 100644 src/utils/get-camel-case.js create mode 100644 src/utils/get-kebab-case.js create mode 100644 src/utils/index.js create mode 100644 src/utils/parse.js create mode 100644 tsconfig.json diff --git a/package.json b/package.json index a6aaa9f..03d175a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "web-component-base", - "version": "2.0.0-beta.1", + "version": "2.0.0-beta.2", "description": "A zero-dependency, ~600 Bytes (minified & gzipped), JS base class for creating reactive custom elements easily", "type": "module", "exports": { @@ -16,6 +16,10 @@ "types": "./attach-effect.d.ts", "import": "./attach-effect.js" }, + "./utils": { + "types": "./utils/index.d.ts", + "import": "./utils/index.js" + }, "./WebComponent.min.js": { "types": "./WebComponent.d.ts", "import": "./WebComponent.min.js" @@ -26,12 +30,11 @@ "start": "npx simple-server .", "demo": "npx simple-server .", "site": "npm start -w site", - "build": "npm run clean && npm run generate:types && npm run copy:meta && npm run copy:source && npm run minify", + "build": "npm run clean && tsc && npm run copy:meta && npm run copy:source && npm run minify", "clean": "rm -rf dist", "minify": "npx uglifyjs ./dist/WebComponent.js -o ./dist/WebComponent.min.js", - "generate:types": "tsc --allowJs src/* --outDir dist --declaration --emitDeclarationOnly", "copy:meta": "node prepare.js && cp README.md ./dist && cp LICENSE ./dist", - "copy:source": "cp ./src/* ./dist", + "copy:source": "cp -r ./src/* ./dist", "pub": "npm run clean && npm run build && cd ./dist && npm publish", "pub:beta": "npm run clean && npm run build && cd ./dist && npm publish --tag beta", "publish:patch": "npm version patch && npm run pub", diff --git a/src/WebComponent.js b/src/WebComponent.js index 5075b87..7faeeb7 100644 --- a/src/WebComponent.js +++ b/src/WebComponent.js @@ -1,3 +1,7 @@ +import { getKebabCase } from "./utils/get-kebab-case"; +import { getCamelCase } from "./utils/get-camel-case"; +import { serialize, deserialize } from "./utils/parse"; + /** * A minimal base class to reduce the complexity of creating reactive custom elements * @license MIT @@ -89,7 +93,7 @@ export class WebComponent extends HTMLElement { } attributeChangedCallback(property, previousValue, currentValue) { - const camelCaps = this.#getCamelCaps(property); + const camelCaps = getCamelCase(property); if (previousValue !== currentValue) { this[property] = currentValue === "" || currentValue; @@ -103,26 +107,16 @@ export class WebComponent extends HTMLElement { } #handleUpdateProp(key, stringifiedValue) { - const restored = this.#deserialize(stringifiedValue, this.#typeMap[key]); + const restored = deserialize(stringifiedValue, this.#typeMap[key]); if (restored !== this.props[key]) this.props[key] = restored; } - #getCamelCaps(kebab) { - return kebab.replace(/-./g, (x) => x[1].toUpperCase()); - } - #typeMap = {}; #effectsMap = {}; #handler(setter, meta) { const effectsMap = meta.#effectsMap; const typeMap = meta.#typeMap; - const getKebab = (str) => { - return str.replace( - /[A-Z]+(?![a-z])|[A-Z]/g, - ($, ofs) => (ofs ? "-" : "") + $.toLowerCase() - ); - }; return { set(obj, prop, value) { @@ -140,9 +134,8 @@ export class WebComponent extends HTMLElement { } else if (oldValue !== value) { obj[prop] = value; effectsMap[prop]?.forEach((f) => f(value)); - const kebab = getKebab(prop); - - setter(kebab, meta.#serialize(value)); + const kebab = getKebabCase(prop); + setter(kebab, serialize(value)); } return true; @@ -158,29 +151,6 @@ export class WebComponent extends HTMLElement { }; } - #deserialize(value, type){ - switch (type) { - case 'number': - case 'boolean': - case 'object': - case 'undefined': - return JSON.parse(value); - default: - return value; - } - }; - - #serialize(value) { - switch(typeof value) { - case 'number': - case 'boolean': - case 'object': - case 'undefined': - return JSON.stringify(value); - default: return value; - } - } - #initializeProps() { if (!this.#props) { this.#props = new Proxy( diff --git a/src/utils/get-camel-case.js b/src/utils/get-camel-case.js new file mode 100644 index 0000000..4bfbeaa --- /dev/null +++ b/src/utils/get-camel-case.js @@ -0,0 +1,3 @@ +export function getCamelCase(kebab) { + return kebab.replace(/-./g, (x) => x[1].toUpperCase()); +} diff --git a/src/utils/get-kebab-case.js b/src/utils/get-kebab-case.js new file mode 100644 index 0000000..3b3a385 --- /dev/null +++ b/src/utils/get-kebab-case.js @@ -0,0 +1,6 @@ +export function getKebabCase(str) { + return str.replace( + /[A-Z]+(?![a-z])|[A-Z]/g, + ($, ofs) => (ofs ? "-" : "") + $.toLowerCase() + ); +} diff --git a/src/utils/index.js b/src/utils/index.js new file mode 100644 index 0000000..7ad1f4d --- /dev/null +++ b/src/utils/index.js @@ -0,0 +1 @@ +export {serialize, deserialize} from './parse.js'; \ No newline at end of file diff --git a/src/utils/parse.js b/src/utils/parse.js new file mode 100644 index 0000000..78a2368 --- /dev/null +++ b/src/utils/parse.js @@ -0,0 +1,23 @@ +export function deserialize(value, type) { + switch (type) { + case "number": + case "boolean": + case "object": + case "undefined": + return JSON.parse(value); + default: + return value; + } +} + +export function serialize(value) { + switch (typeof value) { + case "number": + case "boolean": + case "object": + case "undefined": + return JSON.stringify(value); + default: + return value; + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..f2041ec --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,15 @@ + +{ + "compilerOptions": { + "allowJs": true, + "outDir": "dist", + "declaration": true, + "emitDeclarationOnly": true + }, + "include": [ + "src/*", + ], + "exclude": [ + "src/utils" + ] +}