From 0738aa4cd6cfaa5cdafab66f525993a10b4ec648 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Mon, 11 Nov 2024 14:51:48 -0600 Subject: [PATCH 01/78] feat: card scaffold --- packages/component/src/card/Card.stories.js | 36 +++++++++++++++++++++ packages/component/src/card/Card.ts | 23 +++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 packages/component/src/card/Card.stories.js create mode 100644 packages/component/src/card/Card.ts diff --git a/packages/component/src/card/Card.stories.js b/packages/component/src/card/Card.stories.js new file mode 100644 index 0000000..665dad1 --- /dev/null +++ b/packages/component/src/card/Card.stories.js @@ -0,0 +1,36 @@ +import { CardComponent } from './Card'; + +const PrimaryTemplate = ({ image, headline, content, link }) => ` + + +

${headline}

+

${content}

+ ${link} +
`; + +export const ImageCard = PrimaryTemplate.bind({}); +ImageCard.args = { + image: + 'https://images.unsplash.com/photo-1612392167062-8f76710986ba?ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80', + headline: 'Food', + content: + ' Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ', + link: 'Read', +}; +export default { + title: 'Components/Card', + argTypes: { + image: { + control: { type: 'text' }, + }, + headline: { + control: { type: 'text' }, + }, + content: { + control: { type: 'text' }, + }, + link: { + control: { type: 'text' }, + }, + }, +}; diff --git a/packages/component/src/card/Card.ts b/packages/component/src/card/Card.ts new file mode 100644 index 0000000..ce44740 --- /dev/null +++ b/packages/component/src/card/Card.ts @@ -0,0 +1,23 @@ +export class CardComponent extends HTMLElement { + constructor() { + super(); + + const shadowRoot = this.attachShadow({ mode: 'open' }); + + const template = document.createElement('template'); + template.innerHTML = ` +
+ +
+
+ +
+ + `; + shadowRoot.appendChild(template.content.cloneNode(true)); + } +} + +customElements.define('in-card', CardComponent); From 0c9c73729f237f5bac049cba9efd1ea88f669654 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Mon, 11 Nov 2024 15:44:59 -0600 Subject: [PATCH 02/78] feat: modified css --- packages/style/style.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/style/style.css b/packages/style/style.css index d9589d4..f3687cb 100644 --- a/packages/style/style.css +++ b/packages/style/style.css @@ -176,3 +176,8 @@ label { font-size: var(--font-body-sm); margin-bottom: var(--margin-sm); } + +::slotted(a:link), +::slotted(a:visited) { + display: block; +} From 0df7c71a14adf74729cf41ab80de2433b259877d Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Thu, 14 Nov 2024 03:13:11 -0600 Subject: [PATCH 03/78] page 57 - Styling Content --- packages/component/src/card/Card.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/component/src/card/Card.ts b/packages/component/src/card/Card.ts index ce44740..e42c843 100644 --- a/packages/component/src/card/Card.ts +++ b/packages/component/src/card/Card.ts @@ -6,6 +6,16 @@ export class CardComponent extends HTMLElement { const template = document.createElement('template'); template.innerHTML = ` +
From e93abd412b6acb9e0029ea56c7a072edfeff2e11 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Fri, 15 Nov 2024 00:29:04 -0600 Subject: [PATCH 04/78] started writing integration tests - page 64 --- cypress/integration/Card.spec.js | 0 packages/component/src/card/Card.ts | 28 ++++++++++++++++++++++------ packages/style/style.css | 4 ---- 3 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 cypress/integration/Card.spec.js diff --git a/cypress/integration/Card.spec.js b/cypress/integration/Card.spec.js new file mode 100644 index 0000000..e69de29 diff --git a/packages/component/src/card/Card.ts b/packages/component/src/card/Card.ts index e42c843..42a69a1 100644 --- a/packages/component/src/card/Card.ts +++ b/packages/component/src/card/Card.ts @@ -8,12 +8,28 @@ export class CardComponent extends HTMLElement { template.innerHTML = `
diff --git a/packages/style/style.css b/packages/style/style.css index f3687cb..f136198 100644 --- a/packages/style/style.css +++ b/packages/style/style.css @@ -177,7 +177,3 @@ label { margin-bottom: var(--margin-sm); } -::slotted(a:link), -::slotted(a:visited) { - display: block; -} From b56b5012144cb99eb85928b8fa384356e6eb9e41 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sat, 16 Nov 2024 17:11:02 -0600 Subject: [PATCH 05/78] updated cypress --- cypress.config.ts | 16 + cypress.json | 7 - .../Card.spec.js => e2e/Card.cy.js} | 0 cypress/support/{index.js => e2e.js} | 0 package.json | 4 +- yarn.lock | 326 ++++++++++++++---- 6 files changed, 272 insertions(+), 81 deletions(-) create mode 100644 cypress.config.ts delete mode 100644 cypress.json rename cypress/{integration/Card.spec.js => e2e/Card.cy.js} (100%) rename cypress/support/{index.js => e2e.js} (100%) diff --git a/cypress.config.ts b/cypress.config.ts new file mode 100644 index 0000000..167ada5 --- /dev/null +++ b/cypress.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + defaultCommandTimeout: 30000, + viewportWidth: 1000, + viewportHeight: 568, + includeShadowDOM: true, + e2e: { + // We've imported your old cypress plugins here. + // You may want to clean this up later by importing these. + setupNodeEvents(on, config) { + return require('./cypress/plugins/index.js')(on, config) + }, + baseUrl: 'http://localhost:6006', + }, +}) diff --git a/cypress.json b/cypress.json deleted file mode 100644 index a273d36..0000000 --- a/cypress.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "baseUrl": "http://localhost:6006", - "defaultCommandTimeout": 30000, - "viewportWidth": 1000, - "viewportHeight": 568, - "includeShadowDOM": true -} diff --git a/cypress/integration/Card.spec.js b/cypress/e2e/Card.cy.js similarity index 100% rename from cypress/integration/Card.spec.js rename to cypress/e2e/Card.cy.js diff --git a/cypress/support/index.js b/cypress/support/e2e.js similarity index 100% rename from cypress/support/index.js rename to cypress/support/e2e.js diff --git a/package.json b/package.json index 63df5d2..c77bf31 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,6 @@ "babel-plugin-polyfill-regenerator": "0.3.1", "broadcast-channel": "3.7.0", "concurrently": "6.2.0", - "cypress": "8.6.0", "gh-pages": "3.2.3", "jest": "26.6.3", "lerna": "4.0.0", @@ -59,6 +58,7 @@ "@ungap/custom-elements": "1.0.0", "awesome-typescript-loader": "5.2.1", "broadcastchannel-polyfill": "1.0.1", + "cypress": "^13.15.2", "element-internals-polyfill": "0.1.40", "html-minifier": "4.0.0", "html-webpack-plugin": "5.5.0", @@ -98,4 +98,4 @@ "workspaces": [ "packages/**/*" ] -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 7824842..668e8ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1931,6 +1931,11 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" @@ -1957,10 +1962,10 @@ globby "11.0.4" typescript "~4.3.2" -"@cypress/request@^2.88.6": - version "2.88.6" - resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.6.tgz#a970dd675befc6bdf8a8921576c01f51cc5798e9" - integrity sha512-z0UxBE/+qaESAHY9p9sM2h8Y4XqtsbDCt0/DPOrqA/RZgKi4PkxdpXyK4wCCnSk1xHqWHZZAE+gV6aDAR6+caQ== +"@cypress/request@^3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@cypress/request/-/request-3.0.6.tgz#f5580add6acee0e183b4d4e07eff4f31327ae12b" + integrity sha512-fi0eVdCOtKu5Ed6+E8mYxUF6ZTFJDZvHogCBelM0xVXmrDEkyM22gRArQzq1YcHPm1V47Vf/iAD+WgVdUlJCGg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -1968,17 +1973,16 @@ combined-stream "~1.0.6" extend "~3.0.2" forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" + form-data "~4.0.0" + http-signature "~1.4.0" is-typedarray "~1.0.0" isstream "~0.1.2" json-stringify-safe "~5.0.1" mime-types "~2.1.19" performance-now "^2.1.0" - qs "~6.5.2" + qs "6.13.0" safe-buffer "^5.1.2" - tough-cookie "~2.5.0" + tough-cookie "^5.0.0" tunnel-agent "^0.6.0" uuid "^8.3.2" @@ -4813,7 +4817,7 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.9.tgz#04eb3da65d08ea377f5e682bf0d22dc1f5e7f19e" integrity sha512-HXhRf581nCItzn8yevv4LYt+bJ5cBbDBAJExbDPMeU/2n5/j0ZemGpayahFBP4xL7RseaCLASLD9i9AYyDe7Nw== -"@types/node@^14.0.10", "@types/node@^14.14.31": +"@types/node@^14.0.10": version "14.17.18" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.18.tgz#0198489a751005f71217744aa966cd1f29447c81" integrity sha512-haYyibw4pbteEhkSg0xdDLAI3679L75EJ799ymVrPxOA922bPx3ML59SoDsQ//rHlvqpu+e36kcbR3XRQtFblA== @@ -4923,10 +4927,10 @@ "@types/mime" "^1" "@types/node" "*" -"@types/sinonjs__fake-timers@^6.0.2": - version "6.0.4" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.4.tgz#0ecc1b9259b76598ef01942f547904ce61a6a77d" - integrity sha512-IFQTJARgMUBF+xVd2b+hIgXWrZEjND3vJtRCvIelcFB5SIXfjV4bOHbHJ0eXKh+0COrBRc8MqteKAz/j88rE0A== +"@types/sinonjs__fake-timers@8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" + integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g== "@types/sizzle@^2.3.2": version "2.3.3" @@ -6456,7 +6460,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.2.1, buffer@^5.5.0: +buffer@^5.2.1, buffer@^5.5.0, buffer@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -6590,6 +6594,17 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -6835,10 +6850,10 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -ci-info@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6" - integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A== +ci-info@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.1.0.tgz#92319d2fa29d2620180ea5afed31f589bc98cf83" + integrity sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -6910,15 +6925,14 @@ cli-table3@^0.6.1: optionalDependencies: colors "1.4.0" -cli-table3@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.0.tgz#b7b1bc65ca8e7b5cef9124e13dc2b21e2ce4faee" - integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ== +cli-table3@~0.6.1: + version "0.6.5" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== dependencies: - object-assign "^4.1.0" string-width "^4.2.0" optionalDependencies: - colors "^1.1.2" + "@colors/colors" "1.5.0" cli-truncate@^2.1.0: version "2.1.0" @@ -7051,7 +7065,7 @@ colorette@^2.0.14: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== -colors@1.4.0, colors@^1.1.2: +colors@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -7101,11 +7115,6 @@ commander@^4.1.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - commander@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" @@ -7727,52 +7736,53 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= -cypress@8.6.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-8.6.0.tgz#8d02fa58878b37cfc45bbfce393aa974fa8a8e22" - integrity sha512-F7qEK/6Go5FsqTueR+0wEw2vOVKNgk5847Mys8vsWkzPoEKdxs+7N9Y1dit+zhaZCLtMPyrMwjfA53ZFy+lSww== +cypress@^13.15.2: + version "13.15.2" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.15.2.tgz#ef19554c274bc4ff23802aeb5c52951677fa67f1" + integrity sha512-ARbnUorjcCM3XiPwgHKuqsyr5W9Qn+pIIBPaoilnoBkLdSC2oLQjV1BUpnmc7KR+b7Avah3Ly2RMFnfxr96E/A== dependencies: - "@cypress/request" "^2.88.6" + "@cypress/request" "^3.0.6" "@cypress/xvfb" "^1.2.4" - "@types/node" "^14.14.31" - "@types/sinonjs__fake-timers" "^6.0.2" + "@types/sinonjs__fake-timers" "8.1.1" "@types/sizzle" "^2.3.2" arch "^2.2.0" blob-util "^2.0.2" bluebird "^3.7.2" + buffer "^5.7.1" cachedir "^2.3.0" chalk "^4.1.0" check-more-types "^2.24.0" + ci-info "^4.0.0" cli-cursor "^3.1.0" - cli-table3 "~0.6.0" - commander "^5.1.0" + cli-table3 "~0.6.1" + commander "^6.2.1" common-tags "^1.8.0" dayjs "^1.10.4" - debug "^4.3.2" + debug "^4.3.4" enquirer "^2.3.6" - eventemitter2 "^6.4.3" + eventemitter2 "6.4.7" execa "4.1.0" executable "^4.1.1" extract-zip "2.0.1" figures "^3.2.0" fs-extra "^9.1.0" getos "^3.2.1" - is-ci "^3.0.0" is-installed-globally "~0.4.0" lazy-ass "^1.6.0" listr2 "^3.8.3" lodash "^4.17.21" log-symbols "^4.0.0" - minimist "^1.2.5" + minimist "^1.2.8" ospath "^1.2.2" pretty-bytes "^5.6.0" + process "^0.11.10" proxy-from-env "1.0.0" - ramda "~0.27.1" request-progress "^3.0.0" + semver "^7.5.3" supports-color "^8.1.1" - tmp "~0.2.1" + tmp "~0.2.3" + tree-kill "1.2.2" untildify "^4.0.0" - url "^0.11.0" yauzl "^2.10.0" d@1, d@^1.0.1: @@ -7838,7 +7848,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== @@ -7866,6 +7876,13 @@ debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.4: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -7943,6 +7960,15 @@ defer-to-connect@^1.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -8463,6 +8489,18 @@ es-array-method-boxes-properly@^1.0.0: resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-get-iterator@^1.0.2: version "1.1.2" resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7" @@ -8656,10 +8694,10 @@ event-stream@=3.3.4: stream-combiner "~0.0.4" through "~2.3.1" -eventemitter2@^6.4.3: - version "6.4.4" - resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.4.tgz#aa96e8275c4dbeb017a5d0e03780c65612a1202b" - integrity sha512-HLU3NDY6wARrLCEwyGKRBvuWYyvW6mHYv72SJJAH3iJN3a6eVUvkjFkcxah1bcTgGVBBrFdIopBJPhCQFMLyXw== +eventemitter2@6.4.7: + version "6.4.7" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d" + integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg== eventemitter3@^4.0.4: version "4.0.7" @@ -9205,6 +9243,15 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +form-data@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" + integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + format@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" @@ -9327,6 +9374,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function.prototype.name@^1.1.0: version "1.1.4" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.4.tgz#e4ea839b9d3672ae99d0efd9f38d9191c5eaac83" @@ -9395,6 +9447,17 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -9651,6 +9714,13 @@ glur@^1.1.2: resolved "https://registry.yarnpkg.com/glur/-/glur-1.1.2.tgz#f20ea36db103bfc292343921f1f91e83c3467689" integrity sha1-8g6jbbEDv8KSNDkh8fkeg8NGdok= +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + got@^9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -9742,11 +9812,28 @@ has-glob@^1.0.0: dependencies: is-glob "^3.0.0" +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + has-symbols@^1.0.1, has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + has-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" @@ -9819,6 +9906,13 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + hast-to-hyperscript@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d" @@ -10100,6 +10194,15 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +http-signature@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.4.0.tgz#dee5a9ba2bf49416abc544abd6d967f6a94c8c3f" + integrity sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg== + dependencies: + assert-plus "^1.0.0" + jsprim "^2.0.2" + sshpk "^1.18.0" + https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" @@ -10472,13 +10575,6 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-ci@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.0.tgz#c7e7be3c9d8eef7d0fa144390bd1e4b88dc4c994" - integrity sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ== - dependencies: - ci-info "^3.1.1" - is-core-module@^2.2.0, is-core-module@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" @@ -11463,6 +11559,11 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -11520,6 +11621,16 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsprim@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" + integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + junk@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" @@ -12420,6 +12531,11 @@ minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + minipass-collect@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" @@ -12574,7 +12690,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.0.0, ms@^2.1.1: +ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -13073,6 +13189,11 @@ object-inspect@^1.11.0, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== +object-inspect@^1.13.1: + version "1.13.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a" + integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== + object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -14288,6 +14409,13 @@ q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" + qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -14355,11 +14483,6 @@ ramda@^0.21.0: resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35" integrity sha1-oAGr7bP/YQd9T/HVd9RN536NCjU= -ramda@~0.27.1: - version "0.27.1" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" - integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== - random-bytes@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" @@ -15405,6 +15528,11 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.5.3: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -15471,6 +15599,18 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -15558,6 +15698,16 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + sigmund@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" @@ -15838,6 +15988,21 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +sshpk@^1.18.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -16515,6 +16680,18 @@ tiny-lr@^1.1.1: object-assign "^4.1.0" qs "^6.4.0" +tldts-core@^6.1.61: + version "6.1.61" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.61.tgz#5cd6507535ef5f5027ac9a1f52b9b60ecb9edfbd" + integrity sha512-In7VffkDWUPgwa+c9picLUxvb0RltVwTkSgMNFgvlGSWveCzGBemBqTsgJCL4EDFWZ6WH0fKTsot6yNhzy3ZzQ== + +tldts@^6.1.32: + version "6.1.61" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.1.61.tgz#85df9810aa4c24bff281bf1fd0b838e087beef9c" + integrity sha512-rv8LUyez4Ygkopqn+M6OLItAOT9FF3REpPQDkdMx5ix8w4qkuE7Vo2o/vw1nxKQYmJDV8JpAMJQr1b+lTKf0FA== + dependencies: + tldts-core "^6.1.61" + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -16522,12 +16699,10 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -tmp@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" - integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== - dependencies: - rimraf "^3.0.0" +tmp@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== tmpl@1.0.x: version "1.0.5" @@ -16607,6 +16782,13 @@ tough-cookie@^4.0.0: punycode "^2.1.1" universalify "^0.1.2" +tough-cookie@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-5.0.0.tgz#6b6518e2b5c070cf742d872ee0f4f92d69eac1af" + integrity sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q== + dependencies: + tldts "^6.1.32" + tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -16627,7 +16809,7 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= -tree-kill@^1.2.2: +tree-kill@1.2.2, tree-kill@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== From c7ee93b38eeda97366465052312dca3c8962b1d5 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sat, 16 Nov 2024 18:06:56 -0600 Subject: [PATCH 06/78] finished integration tests --- cypress/e2e/Card.cy.js | 20 ++++++++++++++++++++ snapshots.js | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cypress/e2e/Card.cy.js b/cypress/e2e/Card.cy.js index e69de29..0d12401 100644 --- a/cypress/e2e/Card.cy.js +++ b/cypress/e2e/Card.cy.js @@ -0,0 +1,20 @@ +describe("CardComponent", () => { + it("should find slots in the card", () => { + cy.visit("iframe.html?id=components-card--image-card" + ); + cy.get("in-card").shadow().find('slot[name="header"]' + ).should("exist"); + cy.get("in-card").shadow().find('slot[name="content"]').should("exist"); + cy.get("in-card").shadow().find('slot[name="footer"]' + ).should("exist"); + }); + + it("should find the card slot content in light DOM", () => { + cy.visit("iframe.html?id=components-card--image-card" + ); + cy.get("#root").find('[slot="header"]').get("img").should("exist"); + cy.get("#root").find('[slot="header"]').contains("Food"); + cy.get("#root").find('[slot="content"]').contains("Lorem ipsum"); + cy.get("#root").find('[slot="footer"]').contains("Read"); + }); + }); \ No newline at end of file diff --git a/snapshots.js b/snapshots.js index 5cef2e1..92d14ce 100644 --- a/snapshots.js +++ b/snapshots.js @@ -1,3 +1,3 @@ module.exports = { - "__version": "8.6.0" + "__version": "13.15.2" } From 98bf07a2dc62e9fca5d01f068f0f3eaa718620d1 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sun, 17 Nov 2024 11:49:36 -0600 Subject: [PATCH 07/78] Started chapter 2 - page 82 --- packages/component/src/input/TextInput.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/component/src/input/TextInput.ts diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts new file mode 100644 index 0000000..d8f59ea --- /dev/null +++ b/packages/component/src/input/TextInput.ts @@ -0,0 +1,5 @@ +export class TextInputComponent extends HTMLElement { + constructor() { + super() + } +} \ No newline at end of file From 61852c82c83cc49279d0c966b44e98a279316cd0 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Tue, 19 Nov 2024 06:47:03 -0600 Subject: [PATCH 08/78] added in-textinput story - page 96 --- .../component/src/input/TextInput.stories.js | 14 ++++++++++++++ packages/component/src/input/TextInput.ts | 17 +++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 packages/component/src/input/TextInput.stories.js diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js new file mode 100644 index 0000000..09ae7f5 --- /dev/null +++ b/packages/component/src/input/TextInput.stories.js @@ -0,0 +1,14 @@ +import {TextInputComponent} from './TextInput'; +import {html} from 'lit-html'; + +const PrimaryTemplate = ({}) => html` +
+ +
+`; + +export const Primary = PrimaryTemplate.bind({}); +export default { + title: "Components/Inputs/TextInput", + component: "in-textinput", +} \ No newline at end of file diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index d8f59ea..b1c8476 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -1,5 +1,18 @@ export class TextInputComponent extends HTMLElement { + static formAssociated = true; constructor() { - super() + super(); + const shadowRoot = this.attachShadow({mode: 'open'}); + const template = document.createElement("template"); + + template.innerHTML = ` +
+ +
+
+ `; + shadowRoot.appendChild(template.content.cloneNode(true)); } -} \ No newline at end of file +} + +customElements.define("in-textinput", TextInputComponent); \ No newline at end of file From 0facf248ca6b4011f821cb9c65b21ced7024f4ab Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Wed, 20 Nov 2024 10:53:59 -0600 Subject: [PATCH 09/78] added internals - page 97 --- packages/component/src/input/TextInput.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index b1c8476..624cb31 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -1,18 +1,22 @@ +import { IElementInternals } from 'types/lib.elementInternals'; export class TextInputComponent extends HTMLElement { - static formAssociated = true; - constructor() { - super(); - const shadowRoot = this.attachShadow({mode: 'open'}); - const template = document.createElement("template"); + static formAssociated = true; - template.innerHTML = ` + private internals: IElementInternals; + constructor() { + super(); + const shadowRoot = this.attachShadow({ mode: 'open' }); + const template = document.createElement('template'); + + template.innerHTML = `
`; - shadowRoot.appendChild(template.content.cloneNode(true)); - } + shadowRoot.appendChild(template.content.cloneNode(true)); + this.internals = this.attachInternals(); + } } -customElements.define("in-textinput", TextInputComponent); \ No newline at end of file +customElements.define('in-textinput', TextInputComponent); From d85b477f3ca9fa6a259bc7d609ac54c5243c909f Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Wed, 20 Nov 2024 23:22:53 -0600 Subject: [PATCH 10/78] Where does validation logic belong in the source code? - page 100 --- packages/component/src/input/TextInput.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 624cb31..b444ae9 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -16,6 +16,21 @@ export class TextInputComponent extends HTMLElement { `; shadowRoot.appendChild(template.content.cloneNode(true)); this.internals = this.attachInternals(); + }; + checkValidity() { + return this.internals.checkValidity() + }; + reportValidity() { + return this.internals.reportValidity(); + }; + get validity() { + return this.internals.validity; + }; + get validationMessage() { + return this.internals.validationMessage; + }; + setValidity(flags: ValidityStateFlags, message?: string, anchor?: HTMLElement): void { + this.internals.setValidity(flags, message, anchor) } } From 7a12389a5ed6524d7c8e995e13015ead14997c84 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Wed, 20 Nov 2024 23:26:46 -0600 Subject: [PATCH 11/78] forgot to save - page 100 --- packages/component/src/input/TextInput.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index b444ae9..d451429 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -30,8 +30,8 @@ export class TextInputComponent extends HTMLElement { return this.internals.validationMessage; }; setValidity(flags: ValidityStateFlags, message?: string, anchor?: HTMLElement): void { - this.internals.setValidity(flags, message, anchor) - } + this.internals.setValidity(flags, message, anchor); + }; } customElements.define('in-textinput', TextInputComponent); From 71da5a5287f8ff8b132257e1561104ad35641860 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Mon, 25 Nov 2024 09:01:20 -0600 Subject: [PATCH 12/78] Mocking the Validators in Storybook - page 103 --- packages/component/src/input/validator.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 packages/component/src/input/validator.ts diff --git a/packages/component/src/input/validator.ts b/packages/component/src/input/validator.ts new file mode 100644 index 0000000..3d8b7ef --- /dev/null +++ b/packages/component/src/input/validator.ts @@ -0,0 +1,7 @@ +export type Validator = { + validations: { + flag: ValidityStateFlags; + condition: (elem: HTMLElement) => boolean; + message?: string; + }[]; +}; \ No newline at end of file From 9058e87221f743d97935694ed518920d0f6598c9 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Mon, 25 Nov 2024 20:57:33 -0600 Subject: [PATCH 13/78] started mocking validators for storybook --- .../component/src/input/TextInput.stories.js | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js index 09ae7f5..3646f6a 100644 --- a/packages/component/src/input/TextInput.stories.js +++ b/packages/component/src/input/TextInput.stories.js @@ -1,14 +1,32 @@ import {TextInputComponent} from './TextInput'; import {html} from 'lit-html'; -const PrimaryTemplate = ({}) => html` -
- -
-`; +const PrimaryTemplate = ({}) => { + setTimeout(() => { + const input = document.querySelector(`[name="username"]`); + input.$validator = validators["username"] + }, 0); + return html` +
+ +
` +}; + +const validators = { + username: { + validations: [ + { + flag: {valueMissng: true}, + message: "Error: Required", + condition: (input) => input.required && input.value <= 0, + }, + ], + }, +}; export const Primary = PrimaryTemplate.bind({}); export default { title: "Components/Inputs/TextInput", component: "in-textinput", -} \ No newline at end of file +} + From 4b4dfdb4bf182904428dd6f9f5356775261d3a6a Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Wed, 27 Nov 2024 13:41:37 -0600 Subject: [PATCH 14/78] added validator --- packages/component/src/input/TextInput.ts | 28 +++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index d451429..0477a55 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -1,7 +1,8 @@ import { IElementInternals } from 'types/lib.elementInternals'; +import { Validator } from './validator'; export class TextInputComponent extends HTMLElement { static formAssociated = true; - + public $validator: Validator; private internals: IElementInternals; constructor() { super(); @@ -16,22 +17,31 @@ export class TextInputComponent extends HTMLElement { `; shadowRoot.appendChild(template.content.cloneNode(true)); this.internals = this.attachInternals(); - }; + } checkValidity() { - return this.internals.checkValidity() - }; + return this.internals.checkValidity(); + } reportValidity() { return this.internals.reportValidity(); - }; + } get validity() { return this.internals.validity; - }; + } get validationMessage() { return this.internals.validationMessage; - }; - setValidity(flags: ValidityStateFlags, message?: string, anchor?: HTMLElement): void { + } + + get $input(): HTMLInputElement { + return this.shadowRoot.querySelector('input'); + } + + setValidity( + flags: ValidityStateFlags, + message?: string, + anchor?: HTMLElement + ): void { this.internals.setValidity(flags, message, anchor); - }; + } } customElements.define('in-textinput', TextInputComponent); From a3efe387062b62f734c75738f324a2d992c9ddd2 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Thu, 28 Nov 2024 15:14:24 -0600 Subject: [PATCH 15/78] Passing attribute values to children - page 111 --- .../component/src/input/TextInput.stories.js | 2 +- packages/component/src/input/TextInput.ts | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js index 3646f6a..2df21b0 100644 --- a/packages/component/src/input/TextInput.stories.js +++ b/packages/component/src/input/TextInput.stories.js @@ -8,7 +8,7 @@ const PrimaryTemplate = ({}) => { }, 0); return html`
- +
` }; diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 0477a55..0604363 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -18,6 +18,20 @@ export class TextInputComponent extends HTMLElement { shadowRoot.appendChild(template.content.cloneNode(true)); this.internals = this.attachInternals(); } + + static get observedAttributes() { + return ["required", "value"] + } + attributeChangedCallback(name, prev, next) { + switch (name) { + case "value": + this.value = next + break; + case "required": + this.required = next + break; + } + } checkValidity() { return this.internals.checkValidity(); } @@ -35,6 +49,27 @@ export class TextInputComponent extends HTMLElement { return this.shadowRoot.querySelector('input'); } + set value (value: string) { + this.$input.value = value + } + + get value(): string { + return this.$input.value + } + + set required(value: boolean | string) { + if (value === "true" || value === true) { + this.$input.setAttribute("required", "true") + } + if (value === "false" || value == false) { + this.$input.removeAttribute("required") + } + } + + get required(): boolean { + return this.$input.required + } + setValidity( flags: ValidityStateFlags, message?: string, From c6089d59b906bb5fd9ad64edb3161302874e76d4 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Thu, 28 Nov 2024 15:58:25 -0600 Subject: [PATCH 16/78] Handling validation and child events - page 113 --- packages/component/src/input/TextInput.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 0604363..24e2758 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -4,6 +4,7 @@ export class TextInputComponent extends HTMLElement { static formAssociated = true; public $validator: Validator; private internals: IElementInternals; + private $attr = {} constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' }); @@ -23,6 +24,7 @@ export class TextInputComponent extends HTMLElement { return ["required", "value"] } attributeChangedCallback(name, prev, next) { + this.$attr[name] = next; switch (name) { case "value": this.value = next @@ -32,6 +34,12 @@ export class TextInputComponent extends HTMLElement { break; } } + + connectedCallback() { + for (let prop in this.$attr) { + this.$input.setAttribute(prop, this.$attr[prop]); + } + } checkValidity() { return this.internals.checkValidity(); } From 4faf246f9a5ec620681a533864c2caa7986c14ce Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Fri, 29 Nov 2024 13:35:47 -0600 Subject: [PATCH 17/78] figuring out validations --- .../component/src/input/TextInput.stories.js | 16 +++++++++++--- packages/component/src/input/TextInput.ts | 10 ++++++++- packages/component/src/input/validator.ts | 22 ++++++++++++++++++- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js index 2df21b0..97018c7 100644 --- a/packages/component/src/input/TextInput.stories.js +++ b/packages/component/src/input/TextInput.stories.js @@ -1,13 +1,13 @@ import {TextInputComponent} from './TextInput'; import {html} from 'lit-html'; -const PrimaryTemplate = ({}) => { +const PrimaryTemplate = ({onValidate, validators}) => { setTimeout(() => { const input = document.querySelector(`[name="username"]`); input.$validator = validators["username"] }, 0); return html` -
+
` }; @@ -18,13 +18,23 @@ const validators = { { flag: {valueMissng: true}, message: "Error: Required", - condition: (input) => input.required && input.value <= 0, + condition: (input) => input.required && input.value.length < 2, }, ], }, }; export const Primary = PrimaryTemplate.bind({}); +Primary.args = { + validators, + onValidate: (ev) =>{ + if(!document.querySelector(`[name="username"]`).validity.valid) { + console.warn("INVALID") + } else { + console.log("VALID") + } + } +} export default { title: "Components/Inputs/TextInput", component: "in-textinput", diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 24e2758..2e22afe 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -1,5 +1,5 @@ import { IElementInternals } from 'types/lib.elementInternals'; -import { Validator } from './validator'; +import { Validator, validate } from './validator'; export class TextInputComponent extends HTMLElement { static formAssociated = true; public $validator: Validator; @@ -36,9 +36,13 @@ export class TextInputComponent extends HTMLElement { } connectedCallback() { + this.$input.onblur = ()=> { + this.onValidate(true); + } for (let prop in this.$attr) { this.$input.setAttribute(prop, this.$attr[prop]); } + this.onValidate(false); } checkValidity() { return this.internals.checkValidity(); @@ -46,6 +50,10 @@ export class TextInputComponent extends HTMLElement { reportValidity() { return this.internals.reportValidity(); } + + onValidate(showError: boolean) { + validate(this, showError) + } get validity() { return this.internals.validity; } diff --git a/packages/component/src/input/validator.ts b/packages/component/src/input/validator.ts index 3d8b7ef..fe0e8b6 100644 --- a/packages/component/src/input/validator.ts +++ b/packages/component/src/input/validator.ts @@ -4,4 +4,24 @@ export type Validator = { condition: (elem: HTMLElement) => boolean; message?: string; }[]; -}; \ No newline at end of file +}; + +export function validate(elem: any, showError: boolean) { + if(!elem.$validator || !elem.$validator.validations) { + return; + } + + const activeValidators = []; + elem.$validator.validations.forEach((validator)=> { + if(validator.condition(elem)) { + elem.setValidity(validator.flag, validator.message); + activeValidators.push(validator) + } + }); + + if(!activeValidators.length) { + elem.setValidity({}) + } + + elem.dispatchEvent(new CustomEvent("validate", {bubbles: true})); +} \ No newline at end of file From 3ea2429284e59b5e3c40819929a14f8c41cc5a9d Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sun, 1 Dec 2024 18:42:44 -0600 Subject: [PATCH 18/78] added user feedback --- .../component/src/input/TextInput.stories.js | 1 + packages/component/src/input/TextInput.ts | 7 +++--- packages/component/src/input/validator.ts | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js index 97018c7..fc1f090 100644 --- a/packages/component/src/input/TextInput.stories.js +++ b/packages/component/src/input/TextInput.stories.js @@ -28,6 +28,7 @@ export const Primary = PrimaryTemplate.bind({}); Primary.args = { validators, onValidate: (ev) =>{ + console.log(document.querySelector(`[name="username"]`)); if(!document.querySelector(`[name="username"]`).validity.valid) { console.warn("INVALID") } else { diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 2e22afe..166cafd 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -36,12 +36,13 @@ export class TextInputComponent extends HTMLElement { } connectedCallback() { - this.$input.onblur = ()=> { - this.onValidate(true); - } + for (let prop in this.$attr) { this.$input.setAttribute(prop, this.$attr[prop]); } + this.$input.onblur = ()=> { + this.onValidate(true); + } this.onValidate(false); } checkValidity() { diff --git a/packages/component/src/input/validator.ts b/packages/component/src/input/validator.ts index fe0e8b6..480f9f5 100644 --- a/packages/component/src/input/validator.ts +++ b/packages/component/src/input/validator.ts @@ -11,16 +11,38 @@ export function validate(elem: any, showError: boolean) { return; } + const messageElem = elem.shadowRoot.querySelector(".message") + + if(messageElem) { + messageElem.innerHTML = "" + } + const activeValidators = []; elem.$validator.validations.forEach((validator)=> { if(validator.condition(elem)) { elem.setValidity(validator.flag, validator.message); activeValidators.push(validator) + if(showError) { + if(elem.$input) { + elem.$input.classList.add("error"); + } + if (messageElem) { + const div = document.createElement("div") + div.innerHTML = validator.message; + messageElem.appendChild(div) + } + } } }); if(!activeValidators.length) { elem.setValidity({}) + if (elem.$input) { + elem.$input.classList.remove("error") + } + if(messageElem) { + messageElem.innerHTML = "" + } } elem.dispatchEvent(new CustomEvent("validate", {bubbles: true})); From b0800946f799f28ba0f7ae6984aa68f131b4fb0e Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Mon, 2 Dec 2024 18:58:48 -0600 Subject: [PATCH 19/78] added disabled and error states to storybook --- .../component/src/input/TextInput.stories.js | 23 ++++++++++++++ packages/component/src/input/TextInput.ts | 31 ++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js index fc1f090..3e0b7b0 100644 --- a/packages/component/src/input/TextInput.stories.js +++ b/packages/component/src/input/TextInput.stories.js @@ -12,6 +12,21 @@ const PrimaryTemplate = ({onValidate, validators}) => { ` }; +const DisabledTemplate = ({}) => + html` + ` +const ErrorTemplate = ({}) => { + setTimeout(() => { + const input = document.querySelector(`[name="username"]`); + input.$validator = validators["username"]; + input.focus(); + input.blur(); + }, 0); + return html `` +} const validators = { username: { validations: [ @@ -36,6 +51,14 @@ Primary.args = { } } } + +export const Disabled = DisabledTemplate.bind({}) +DisabledTemplate.args = {}; + +export const Error = ErrorTemplate.bind({}) +ErrorTemplate.args = {} + + export default { title: "Components/Inputs/TextInput", component: "in-textinput", diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 166cafd..95ce1a7 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -21,7 +21,7 @@ export class TextInputComponent extends HTMLElement { } static get observedAttributes() { - return ["required", "value"] + return ["required", "value", "disabled"] } attributeChangedCallback(name, prev, next) { this.$attr[name] = next; @@ -32,6 +32,9 @@ export class TextInputComponent extends HTMLElement { case "required": this.required = next break; + case "disabled": + this.disabled = next; + break; } } @@ -45,6 +48,10 @@ export class TextInputComponent extends HTMLElement { } this.onValidate(false); } + + formDisabledCallback(disabled) { + this.disabled = disabled; + } checkValidity() { return this.internals.checkValidity(); } @@ -55,6 +62,26 @@ export class TextInputComponent extends HTMLElement { onValidate(showError: boolean) { validate(this, showError) } + + focus() { + this.$input.focus() + } + + blur() { + this.$input.blur() + } + + set disabled (value: boolean | string) { + if (value === "true" || value === true) { + this.$input.setAttribute("disabled", "true") + } + if (value === "false" || value === false) { + this.$input.removeAttribute("disabled") + } + } + get disabled() { + return this.$input.disabled; + } get validity() { return this.internals.validity; } @@ -66,6 +93,8 @@ export class TextInputComponent extends HTMLElement { return this.shadowRoot.querySelector('input'); } + + set value (value: string) { this.$input.value = value } From 0c1f6a0ff4b1acbafb7c4cd2dbc28a38ae240f8f Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Tue, 3 Dec 2024 20:58:10 -0600 Subject: [PATCH 20/78] styled inputs --- packages/component/src/input/TextInput.ts | 48 +++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 95ce1a7..750eb79 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -11,6 +11,54 @@ export class TextInputComponent extends HTMLElement { const template = document.createElement('template'); template.innerHTML = ` +
From a17c9cb304f44222486e011d9e9f0e678e9bd92a Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Wed, 4 Dec 2024 19:27:59 -0600 Subject: [PATCH 21/78] added getters and setters for a more stable api --- packages/component/src/input/TextInput.ts | 73 ++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 750eb79..1a46658 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -69,7 +69,7 @@ export class TextInputComponent extends HTMLElement { } static get observedAttributes() { - return ["required", "value", "disabled"] + return ["name", "type", "required","minlength", "maxlength","pattern","list","placeholder","readonly", "spellcheck", "value", "disabled"] } attributeChangedCallback(name, prev, next) { this.$attr[name] = next; @@ -83,6 +83,29 @@ export class TextInputComponent extends HTMLElement { case "disabled": this.disabled = next; break; + case "type": + this.$input.setAttribute("type", next); + break; + case "minlength": + this.$input.setAttribute("minlength", next); + break; + case "maxlength": + this.$input.setAttribute("maxlength", next); + break; + case "pattern": + this.$input.setAttribute("pattern", next); + break; + case "list": + this.$input.setAttribute("list", next); + break; + case "placeholder": + this.$input.setAttribute("placeholder", next); + break; + case "readonly": + this.$input.setAttribute("readonly", next); + case "spellcheck": + this.$input.setAttribute("spellcheck", next); + break; } } @@ -119,6 +142,54 @@ export class TextInputComponent extends HTMLElement { this.$input.blur() } + get type() { + return this.$input.type ?? "text"; + } + + set type(type: string) { + this.$input.setAttribute("type" , type); + } + + get list() { + return this.$input.list; + } + + get minLength() { + return this.$input.minLength; + } + + set minLength(min: number) { + this.$input.minLength = min + } + + get maxLength() { + return this.$input.maxLength; + } + + set maxLength(max: number) { + this.$input.maxLength = max; + } + + get readOnly () { + return this.$input.readOnly; + } + + get pattern() { + return this.$input.pattern; + } + + set pattern(pattern: string) { + this.$input.pattern = pattern; + } + + get placeholder() { + return this.$input.placeholder + } + + get spellcheck() { + return this.$input.spellcheck; + } + set disabled (value: boolean | string) { if (value === "true" || value === true) { this.$input.setAttribute("disabled", "true") From 84610fc23b4e1ecc5cb93220e32705a39a6d18fc Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Thu, 5 Dec 2024 02:12:52 -0600 Subject: [PATCH 22/78] started form story --- .../component/src/input/TextInput.stories.js | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js index 3e0b7b0..986eea6 100644 --- a/packages/component/src/input/TextInput.stories.js +++ b/packages/component/src/input/TextInput.stories.js @@ -27,16 +27,72 @@ const ErrorTemplate = ({}) => { }, 0); return html `` } + +const FormTemplate = ({ headline, onSubmit, onValidate, onFormData}) => { + return html` +

${headline}

+
+
+ Login Form + + +
+
+ ` +} const validators = { username: { validations: [ { - flag: {valueMissng: true}, - message: "Error: Required", - condition: (input) => input.required && input.value.length < 2, + flag: {valueMissing: true}, + message: "Error: Required, please enter a username", + condition: (input) => input.required && input.value.length <= 0, }, + { + flag: { tooShort: true}, + message: "Error: Minimum length not met, please supply a value with at least 8 characters.", + condition: (input) => input.minLength && input.value.length < input.minLength + } ], }, + password: { + validations: [ + { + flag: { valueMissing: true }, + message: 'Error: Required, please enter a username.', + condition: (input) => input.required && input.value.length <= 0, + }, + { + flag: { tooShort: true }, + message: + 'Error: Minimum length not met, please supply a value with at least 8 characters.', + condition: (input) => + input.minLength && input.value.length < input.minLength, + }, + { + flag: { patternMismatch: true }, + message: + 'Please use at least one uppercase, uppercase letter, special character, and number.', + condition: (input) => + input.pattern && + input.value.match(new RegExp(input.pattern)) === null, + }, + ], + } + }; export const Primary = PrimaryTemplate.bind({}); @@ -59,6 +115,7 @@ export const Error = ErrorTemplate.bind({}) ErrorTemplate.args = {} + export default { title: "Components/Inputs/TextInput", component: "in-textinput", From 15e01a0e773a60d7092767aeaceae01cb844f9fe Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Fri, 6 Dec 2024 18:40:48 -0600 Subject: [PATCH 23/78] made the form, now to handle the submission --- .../component/src/input/TextInput.stories.js | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js index 986eea6..a51e1ad 100644 --- a/packages/component/src/input/TextInput.stories.js +++ b/packages/component/src/input/TextInput.stories.js @@ -29,6 +29,11 @@ const ErrorTemplate = ({}) => { } const FormTemplate = ({ headline, onSubmit, onValidate, onFormData}) => { + setTimeout(() => { + for(let prop in validators) { + document.querySelector(`[name="${prop}"]`).$validator = validators[prop] + } + }, 0); return html`

${headline}

{ minlength="8" class="form-control" > + + +
` @@ -114,7 +129,31 @@ DisabledTemplate.args = {}; export const Error = ErrorTemplate.bind({}) ErrorTemplate.args = {} - +export const Form = FormTemplate.bind({}); +Form.args = { + headline: "Login", + onSubmit: (ev) => { + console.log(new FormData(ev.target)); + ev.preventDefault(); + }, + onFormData: (ev) => { + console.log(ev); + for(let value of ev.formData.values()) { + console.log(value) + } + }, + onValidat: (ev) => { + const validations = []; + for(let prop in validators) { + validations.push(document.querySelector(`[name="${prop}"]`).validity.valid) + } + if(validations.filter((val)=> val == false).length) { + console.warn("INVALID"); + } else { + console.log("VALID") + } + } +} export default { title: "Components/Inputs/TextInput", From 4f580003cc31fe78ec5608f2b5384d249a96accb Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sat, 7 Dec 2024 17:21:27 -0600 Subject: [PATCH 24/78] started adding form state callbacks --- packages/component/src/input/TextInput.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 1a46658..2be88e8 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -118,6 +118,9 @@ export class TextInputComponent extends HTMLElement { this.onValidate(true); } this.onValidate(false); + this.$input.onchange = () => { + this.onChange() + } } formDisabledCallback(disabled) { @@ -142,6 +145,12 @@ export class TextInputComponent extends HTMLElement { this.$input.blur() } + onChange() { + this.shadowRoot.querySelector(".message").innerHTML = "" + this.$input.classList.remove("error") + this.internals.setFormValue(this.value, this.value) + } + get type() { return this.$input.type ?? "text"; } From e7923a6e2734715b32057b9b16ed8933c89dd37e Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Mon, 9 Dec 2024 21:12:27 -0600 Subject: [PATCH 25/78] finished chapter 2 --- cypress/e2e/TextInput.cy.js | 43 +++++ ...t-js-storyshots-default-primary-1-snap.png | Bin 0 -> 7023 bytes ...hots-components-card-image-card-1-snap.png | Bin 0 -> 152406 bytes ...ents-inputs-text-input-disabled-1-snap.png | Bin 0 -> 6655 bytes ...ponents-inputs-text-input-error-1-snap.png | Bin 0 -> 6906 bytes ...mponents-inputs-text-input-form-1-snap.png | Bin 0 -> 10570 bytes ...nents-inputs-text-input-primary-1-snap.png | Bin 0 -> 4123 bytes .../component/src/input/TextInput.stories.js | 169 +++++++++--------- packages/component/src/input/TextInput.ts | 8 + 9 files changed, 138 insertions(+), 82 deletions(-) create mode 100644 cypress/e2e/TextInput.cy.js create mode 100644 packages/component/packages/component/src/__snapshots__/web-components-storyshots-test-js-storyshots-default-primary-1-snap.png create mode 100644 packages/component/packages/component/src/card/__snapshots__/web-components-storyshots-test-js-storyshots-components-card-image-card-1-snap.png create mode 100644 packages/component/packages/component/src/input/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-text-input-disabled-1-snap.png create mode 100644 packages/component/packages/component/src/input/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-text-input-error-1-snap.png create mode 100644 packages/component/packages/component/src/input/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-text-input-form-1-snap.png create mode 100644 packages/component/packages/component/src/input/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-text-input-primary-1-snap.png diff --git a/cypress/e2e/TextInput.cy.js b/cypress/e2e/TextInput.cy.js new file mode 100644 index 0000000..9dcad32 --- /dev/null +++ b/cypress/e2e/TextInput.cy.js @@ -0,0 +1,43 @@ +describe("TextInputComponent", ()=> { + it("should display error message on blur", () => { + cy.visit("iframe.html?id=components-inputs-textinput--form"); + cy.get("#root").get('[id="username"]').should("be.visible").click(); + cy.get("#root").get('[id="password"]').should("be.visible").click(); + cy.get("#root").get(".submit").should("be.visible").click(); + cy.get("#root") + .get('[id="username"]') + .shadow() + .find(".message") + .contains("Error: Required, please enter a username."); + cy.get("#root") + .get('[id="password"]') + .shadow() + .find(".message") + .contains("Minimum length not met, please supply a value with at least 8 characters."); + }); + it("should not display error message when valid", () => { + cy.visit("iframe.html?id=components-inputs-textinput--form"); + cy.get("#root") + .get('[id="username"]') + .shadow() + .find('input') + .type("jane@doe.com") + cy.get("#root") + .get('[id="password"]') + .shadow() + .find("input") + .type("W3BC0mpon3nts!") + cy.get("#root").get(".submit").should("be.visible").click(); + cy.get("#root") + .get('[id="username"]') + .shadow() + .find('.message') + .should("include.text", "") + cy.get("#root") + .get('[id="password"]') + .shadow() + .find('.message') + .should("include.text", "") + + }) +}) \ No newline at end of file diff --git a/packages/component/packages/component/src/__snapshots__/web-components-storyshots-test-js-storyshots-default-primary-1-snap.png b/packages/component/packages/component/src/__snapshots__/web-components-storyshots-test-js-storyshots-default-primary-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..f7f8e0f59cea4681bfc749514a32d224881e9e14 GIT binary patch literal 7023 zcmeHM`Cn3L-==J`nNp*sOiL-97Atj}az&x%iE^^i5iM7wa?I3(P{9@Ksh-3%of$2r z+{TPtfyjM>W-@6+u~gLDC`@rd5jWg6G9N67`=%H=HsgqkuVgE|941jBN25Z0f^rBm49{X}< zyK($}qXG+y{gk~getMSv;*+_PuCS_L%Z%TE1idie;=7@`XO-7yjYyp+Rocqp24t(Y z3^b~B*;dx~6zlXg40d~yAnyH6;1$Y#(-s))m$SFQebE2aZO_3|^9l*#;>C*zRJnxD zzvwUTt3I*Y)cad=-h%XMPW*N&Lf@VwU2{Tv1z6dfDac9shdf6Fxz+i+0h1}B8 zLhAGid>fRXMQJ!?+nsLWCLPWo5_-SrgsE3mg4-K3o}Et6CJjFcJe#0xApL8rd9p;k zrcy+gs42|!8#ivyD8sUdJ<2%LMyP5!tflCp!(0l$+&j502jiHz}`XZE1Y) zcmI^c#Ti+?TyZ5oJ0^HmAwhSte00t0XR(k&Vlsbqg6JTFS}>eljQo|@lN5$dyT&-eQ)LVI`j*N~V0$k%{P;q!4DpTD){FSgixzPGa{{GCNYMY2M1+nb#!q~i;AyajRKxG2#_}=yw$te8$o``)05r@iZb>3Ya@x} zCAql=Y9bYe<6RtL`yNmSF$vWF8BxOHMvS&aeg3cRwb_vmT+(2pXL<0YZ3cEH&!+6t zgKP4hcvaoH3WWnL59wlCgbz1g?qaS?5aW|T!5zEUxIDLfXC>2|YGQS>`&PH@Nh_ zTLFvpkhZ#HKrv(ZhMlvY>u_Vum&U8tem@cDJS+cr!j3%ltuE-%t1b?`Af^i$R;FWP zW7j78suS*A1(nPLYsE5R{oLgXIVcB_gQ{<&qtI=3vL8v{Ee>DqN}8SMwIgK zs%LFvs%1!L!zB;gKL*TjH4R`7pRA+gvcaxOqU3jLqTfHe+sZPb-F+z^1C(RM91wqB zb@*VcWZ4gc@eOaWw1^ma4{eLV9QUa>9y2f3v$V7%iEL#J%}-AFD+cNl_C>;ADbLF8 z!i~?S(~lr2@+0aM8M-(X_`twARnPZ?2$7Ld>3<0{k(S}hhq+RT~aCVW8>pOgUCKtCzF7=G4Vm8rewVn zO+}ZAo2+@thdbZ_O6gl>I(BW26aT2Erw8lf;{$NTy_1dedEuPp{o=wCEco)TdtZyA z6+Pv}v!J;;Iy)Z+=1}Kf3Ucv$8nB37Q>KDd0DsKju2!Kv?z@kB{$%vbe)^p;WO_Cq z4ZM^riXxp%m~|i~W<^Cshgkdw%r4{p{rl5H=JD0;M<0zvfl)dJcfG$&4?9^i&i;Wo zP=_sacd8`xH}w+v{lR7#)X;pHCIFWJ z_1bD^j|!jw&gdBi^TaCDyIM66D=cu$1H1JSYFRA;PJo&5+2kX_$EL@+@bT0{`VV1W z-hl+9+E4#T?nA7OI5K%W-p!A%m^b@t$}t!{G%YTAMJW(M

TemdQ_msmF1y%9D= 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 D#Sh%+ literal 0 HcmV?d00001 diff --git a/packages/component/packages/component/src/input/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-text-input-form-1-snap.png b/packages/component/packages/component/src/input/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-text-input-form-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..3a7888c20b849709e42ed53380de33ca0873e2ac GIT binary patch literal 10570 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

()UiVdL)ZemrO-T{Bg? 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 YczL(4Nsk_fKj7fZNpeoliA&f210!p`4*&oF literal 0 HcmV?d00001 diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js index a51e1ad..063fc47 100644 --- a/packages/component/src/input/TextInput.stories.js +++ b/packages/component/src/input/TextInput.stories.js @@ -1,23 +1,88 @@ import {TextInputComponent} from './TextInput'; import {html} from 'lit-html'; -const PrimaryTemplate = ({onValidate, validators}) => { +export default { + title: "Components/Inputs/TextInput", + component: "in-textinput", +}; + +const validators = { + username: { + validations: [ + { + flag: { valueMissing: true }, + message: 'Error: Required, please enter a username.', + condition: (input) => input.required && input.value.length <= 0, + }, + { + flag: { tooShort: true }, + message: + 'Error: Minimum length not met, please supply a value with at least 8 characters.', + condition: (input) => + input.minLength && input.value.length < input.minLength, + }, + ], + }, + password: { + validations: [ + { + flag: { valueMissing: true }, + message: 'Error: Required, please enter a password.', + condition: (input) => input.required && input.value.length <= 0, + }, + { + flag: { tooShort: true }, + message: + 'Error: Minimum length not met, please supply a value with at least 8 characters.', + condition: (input) => + input.minLength && input.value.length < input.minLength, + }, + { + flag: { patternMismatch: true }, + message: + 'Please use at least one uppercase, lowercase letter, special character, and number.', + condition: (input) => + input.pattern && + input.value.match(new RegExp(input.pattern)) === null, + }, + ], + }, + }; + + const PrimaryTemplate = ({ onValidate, validators }) => { setTimeout(() => { - const input = document.querySelector(`[name="username"]`); - input.$validator = validators["username"] + const input = document.querySelector(`[name="username"]`); + input.$validator = validators['username']; }, 0); - return html` -

- -
` -}; + return html`
+ +
`; + }; + + export const Primary = PrimaryTemplate.bind({}); +Primary.args = { + validators, + onValidate: (ev) =>{ + console.log(document.querySelector(`[name="username"]`)); + if(!document.querySelector(`[name="username"]`).validity.valid) { + console.warn("INVALID") + } else { + console.log("VALID") + } + } +} + const DisabledTemplate = ({}) => html` - ` + ` +export const Disabled = DisabledTemplate.bind({}) +DisabledTemplate.args = {}; + + const ErrorTemplate = ({}) => { setTimeout(() => { const input = document.querySelector(`[name="username"]`); @@ -28,6 +93,9 @@ const ErrorTemplate = ({}) => { return html `` } +export const Error = ErrorTemplate.bind({}) +ErrorTemplate.args = {} + const FormTemplate = ({ headline, onSubmit, onValidate, onFormData}) => { setTimeout(() => { for(let prop in validators) { @@ -37,19 +105,19 @@ const FormTemplate = ({ headline, onSubmit, onValidate, onFormData}) => { return html`

${headline}

+ name="foo" + slot="content" + @formdata="${onFormData}" + @validate="${onValidate}" + @submit="${onSubmit}" + >
Login Form { name="password" required minlength="8" - pattern="(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(20 ?=.*?[#?!@$ %^&*-]).{8,}$" + pattern="^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,}$" >
` } -const validators = { - username: { - validations: [ - { - flag: {valueMissing: true}, - message: "Error: Required, please enter a username", - condition: (input) => input.required && input.value.length <= 0, - }, - { - flag: { tooShort: true}, - message: "Error: Minimum length not met, please supply a value with at least 8 characters.", - condition: (input) => input.minLength && input.value.length < input.minLength - } - ], - }, - password: { - validations: [ - { - flag: { valueMissing: true }, - message: 'Error: Required, please enter a username.', - condition: (input) => input.required && input.value.length <= 0, - }, - { - flag: { tooShort: true }, - message: - 'Error: Minimum length not met, please supply a value with at least 8 characters.', - condition: (input) => - input.minLength && input.value.length < input.minLength, - }, - { - flag: { patternMismatch: true }, - message: - 'Please use at least one uppercase, uppercase letter, special character, and number.', - condition: (input) => - input.pattern && - input.value.match(new RegExp(input.pattern)) === null, - }, - ], - } - -}; - -export const Primary = PrimaryTemplate.bind({}); -Primary.args = { - validators, - onValidate: (ev) =>{ - console.log(document.querySelector(`[name="username"]`)); - if(!document.querySelector(`[name="username"]`).validity.valid) { - console.warn("INVALID") - } else { - console.log("VALID") - } - } -} - -export const Disabled = DisabledTemplate.bind({}) -DisabledTemplate.args = {}; - -export const Error = ErrorTemplate.bind({}) -ErrorTemplate.args = {} export const Form = FormTemplate.bind({}); Form.args = { @@ -142,7 +150,7 @@ Form.args = { console.log(value) } }, - onValidat: (ev) => { + onValidate: (ev) => { const validations = []; for(let prop in validators) { validations.push(document.querySelector(`[name="${prop}"]`).validity.valid) @@ -155,8 +163,5 @@ Form.args = { } } -export default { - title: "Components/Inputs/TextInput", - component: "in-textinput", -} + diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 2be88e8..fd8a82d 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -126,6 +126,14 @@ export class TextInputComponent extends HTMLElement { formDisabledCallback(disabled) { this.disabled = disabled; } + + formStateRestoreCallback(state: string, mode: string) { + this.value = state; + } + + formResetCallback(state: string) { + this.value = this.getAttribute("value") || ""; + } checkValidity() { return this.internals.checkValidity(); } From 9fd67be42d21d364c663fe6f42821744d716213b Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Tue, 10 Dec 2024 18:00:37 -0600 Subject: [PATCH 26/78] created button component and story --- cypress/e2e/Card.cy.js | 36 +-- cypress/e2e/TextInput.cy.js | 87 +++--- .../component/src/button/Button.stories.js | 1 + packages/component/src/button/Button.ts | 7 + .../component/src/input/TextInput.stories.js | 285 +++++++++--------- packages/component/src/input/TextInput.ts | 120 ++++---- packages/component/src/input/validator.ts | 74 ++--- packages/component/tsconfig.json | 11 +- 8 files changed, 317 insertions(+), 304 deletions(-) create mode 100644 packages/component/src/button/Button.stories.js create mode 100644 packages/component/src/button/Button.ts diff --git a/cypress/e2e/Card.cy.js b/cypress/e2e/Card.cy.js index 0d12401..6b88dda 100644 --- a/cypress/e2e/Card.cy.js +++ b/cypress/e2e/Card.cy.js @@ -1,20 +1,16 @@ -describe("CardComponent", () => { - it("should find slots in the card", () => { - cy.visit("iframe.html?id=components-card--image-card" - ); - cy.get("in-card").shadow().find('slot[name="header"]' - ).should("exist"); - cy.get("in-card").shadow().find('slot[name="content"]').should("exist"); - cy.get("in-card").shadow().find('slot[name="footer"]' - ).should("exist"); - }); - - it("should find the card slot content in light DOM", () => { - cy.visit("iframe.html?id=components-card--image-card" - ); - cy.get("#root").find('[slot="header"]').get("img").should("exist"); - cy.get("#root").find('[slot="header"]').contains("Food"); - cy.get("#root").find('[slot="content"]').contains("Lorem ipsum"); - cy.get("#root").find('[slot="footer"]').contains("Read"); - }); - }); \ No newline at end of file +describe('CardComponent', () => { + it('should find slots in the card', () => { + cy.visit('iframe.html?id=components-card--image-card'); + cy.get('in-card').shadow().find('slot[name="header"]').should('exist'); + cy.get('in-card').shadow().find('slot[name="content"]').should('exist'); + cy.get('in-card').shadow().find('slot[name="footer"]').should('exist'); + }); + + it('should find the card slot content in light DOM', () => { + cy.visit('iframe.html?id=components-card--image-card'); + cy.get('#root').find('[slot="header"]').get('img').should('exist'); + cy.get('#root').find('[slot="header"]').contains('Food'); + cy.get('#root').find('[slot="content"]').contains('Lorem ipsum'); + cy.get('#root').find('[slot="footer"]').contains('Read'); + }); +}); diff --git a/cypress/e2e/TextInput.cy.js b/cypress/e2e/TextInput.cy.js index 9dcad32..0988686 100644 --- a/cypress/e2e/TextInput.cy.js +++ b/cypress/e2e/TextInput.cy.js @@ -1,43 +1,44 @@ -describe("TextInputComponent", ()=> { - it("should display error message on blur", () => { - cy.visit("iframe.html?id=components-inputs-textinput--form"); - cy.get("#root").get('[id="username"]').should("be.visible").click(); - cy.get("#root").get('[id="password"]').should("be.visible").click(); - cy.get("#root").get(".submit").should("be.visible").click(); - cy.get("#root") - .get('[id="username"]') - .shadow() - .find(".message") - .contains("Error: Required, please enter a username."); - cy.get("#root") - .get('[id="password"]') - .shadow() - .find(".message") - .contains("Minimum length not met, please supply a value with at least 8 characters."); - }); - it("should not display error message when valid", () => { - cy.visit("iframe.html?id=components-inputs-textinput--form"); - cy.get("#root") - .get('[id="username"]') - .shadow() - .find('input') - .type("jane@doe.com") - cy.get("#root") - .get('[id="password"]') - .shadow() - .find("input") - .type("W3BC0mpon3nts!") - cy.get("#root").get(".submit").should("be.visible").click(); - cy.get("#root") - .get('[id="username"]') - .shadow() - .find('.message') - .should("include.text", "") - cy.get("#root") - .get('[id="password"]') - .shadow() - .find('.message') - .should("include.text", "") - - }) -}) \ No newline at end of file +describe('TextInputComponent', () => { + it('should display error message on blur', () => { + cy.visit('iframe.html?id=components-inputs-textinput--form'); + cy.get('#root').get('[id="username"]').should('be.visible').click(); + cy.get('#root').get('[id="password"]').should('be.visible').click(); + cy.get('#root').get('.submit').should('be.visible').click(); + cy.get('#root') + .get('[id="username"]') + .shadow() + .find('.message') + .contains('Error: Required, please enter a username.'); + cy.get('#root') + .get('[id="password"]') + .shadow() + .find('.message') + .contains( + 'Minimum length not met, please supply a value with at least 8 characters.' + ); + }); + it('should not display error message when valid', () => { + cy.visit('iframe.html?id=components-inputs-textinput--form'); + cy.get('#root') + .get('[id="username"]') + .shadow() + .find('input') + .type('jane@doe.com'); + cy.get('#root') + .get('[id="password"]') + .shadow() + .find('input') + .type('W3BC0mpon3nts!'); + cy.get('#root').get('.submit').should('be.visible').click(); + cy.get('#root') + .get('[id="username"]') + .shadow() + .find('.message') + .should('include.text', ''); + cy.get('#root') + .get('[id="password"]') + .shadow() + .find('.message') + .should('include.text', ''); + }); +}); diff --git a/packages/component/src/button/Button.stories.js b/packages/component/src/button/Button.stories.js new file mode 100644 index 0000000..f00b9d7 --- /dev/null +++ b/packages/component/src/button/Button.stories.js @@ -0,0 +1 @@ +import { ButtonComponent } from './Button'; diff --git a/packages/component/src/button/Button.ts b/packages/component/src/button/Button.ts new file mode 100644 index 0000000..980c5b0 --- /dev/null +++ b/packages/component/src/button/Button.ts @@ -0,0 +1,7 @@ +export class ButtonComponent extends HTMLButtonElement { + constructor() { + super(); + } +} + +customElements.define('in-button', ButtonComponent, { extends: 'button' }); diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js index 063fc47..c118782 100644 --- a/packages/component/src/input/TextInput.stories.js +++ b/packages/component/src/input/TextInput.stories.js @@ -1,167 +1,170 @@ -import {TextInputComponent} from './TextInput'; -import {html} from 'lit-html'; +import { TextInputComponent } from './TextInput'; +import { html } from 'lit-html'; export default { - title: "Components/Inputs/TextInput", - component: "in-textinput", + title: 'Components/Inputs/TextInput', + component: 'in-textinput', }; const validators = { - username: { - validations: [ - { - flag: { valueMissing: true }, - message: 'Error: Required, please enter a username.', - condition: (input) => input.required && input.value.length <= 0, - }, - { - flag: { tooShort: true }, - message: - 'Error: Minimum length not met, please supply a value with at least 8 characters.', - condition: (input) => - input.minLength && input.value.length < input.minLength, - }, - ], - }, - password: { - validations: [ - { - flag: { valueMissing: true }, - message: 'Error: Required, please enter a password.', - condition: (input) => input.required && input.value.length <= 0, - }, - { - flag: { tooShort: true }, - message: - 'Error: Minimum length not met, please supply a value with at least 8 characters.', - condition: (input) => - input.minLength && input.value.length < input.minLength, - }, - { - flag: { patternMismatch: true }, - message: - 'Please use at least one uppercase, lowercase letter, special character, and number.', - condition: (input) => - input.pattern && - input.value.match(new RegExp(input.pattern)) === null, - }, - ], - }, - }; + username: { + validations: [ + { + flag: { valueMissing: true }, + message: 'Error: Required, please enter a username.', + condition: (input) => input.required && input.value.length <= 0, + }, + { + flag: { tooShort: true }, + message: + 'Error: Minimum length not met, please supply a value with at least 8 characters.', + condition: (input) => + input.minLength && input.value.length < input.minLength, + }, + ], + }, + password: { + validations: [ + { + flag: { valueMissing: true }, + message: 'Error: Required, please enter a password.', + condition: (input) => input.required && input.value.length <= 0, + }, + { + flag: { tooShort: true }, + message: + 'Error: Minimum length not met, please supply a value with at least 8 characters.', + condition: (input) => + input.minLength && input.value.length < input.minLength, + }, + { + flag: { patternMismatch: true }, + message: + 'Please use at least one uppercase, lowercase letter, special character, and number.', + condition: (input) => + input.pattern && + input.value.match(new RegExp(input.pattern)) === null, + }, + ], + }, +}; - const PrimaryTemplate = ({ onValidate, validators }) => { - setTimeout(() => { - const input = document.querySelector(`[name="username"]`); - input.$validator = validators['username']; - }, 0); - return html`
- -
`; - }; +const PrimaryTemplate = ({ onValidate, validators }) => { + setTimeout(() => { + const input = document.querySelector(`[name="username"]`); + input.$validator = validators['username']; + }, 0); + return html`
+ +
`; +}; - export const Primary = PrimaryTemplate.bind({}); +export const Primary = PrimaryTemplate.bind({}); Primary.args = { - validators, - onValidate: (ev) =>{ - console.log(document.querySelector(`[name="username"]`)); - if(!document.querySelector(`[name="username"]`).validity.valid) { - console.warn("INVALID") - } else { - console.log("VALID") - } + validators, + onValidate: (ev) => { + console.log(document.querySelector(`[name="username"]`)); + if (!document.querySelector(`[name="username"]`).validity.valid) { + console.warn('INVALID'); + } else { + console.log('VALID'); } -} - + }, +}; const DisabledTemplate = ({}) => - html` - ` -export const Disabled = DisabledTemplate.bind({}) + html` `; +export const Disabled = DisabledTemplate.bind({}); DisabledTemplate.args = {}; - const ErrorTemplate = ({}) => { - setTimeout(() => { - const input = document.querySelector(`[name="username"]`); - input.$validator = validators["username"]; - input.focus(); - input.blur(); - }, 0); - return html `` -} + setTimeout(() => { + const input = document.querySelector(`[name="username"]`); + input.$validator = validators['username']; + input.focus(); + input.blur(); + }, 0); + return html``; +}; -export const Error = ErrorTemplate.bind({}) -ErrorTemplate.args = {} +export const Error = ErrorTemplate.bind({}); +ErrorTemplate.args = {}; -const FormTemplate = ({ headline, onSubmit, onValidate, onFormData}) => { - setTimeout(() => { - for(let prop in validators) { - document.querySelector(`[name="${prop}"]`).$validator = validators[prop] - } - }, 0); - return html` -

${headline}

-
{ + setTimeout(() => { + for (let prop in validators) { + document.querySelector(`[name="${prop}"]`).$validator = validators[prop]; + } + }, 0); + return html` +

${headline}

+ -
- Login Form - - - - - -
-
- ` -} +
+ Login Form + + + + + +
+ + `; +}; export const Form = FormTemplate.bind({}); Form.args = { - headline: "Login", - onSubmit: (ev) => { - console.log(new FormData(ev.target)); - ev.preventDefault(); - }, - onFormData: (ev) => { - console.log(ev); - for(let value of ev.formData.values()) { - console.log(value) - } - }, - onValidate: (ev) => { - const validations = []; - for(let prop in validators) { - validations.push(document.querySelector(`[name="${prop}"]`).validity.valid) - } - if(validations.filter((val)=> val == false).length) { - console.warn("INVALID"); - } else { - console.log("VALID") - } + headline: 'Login', + onSubmit: (ev) => { + console.log(new FormData(ev.target)); + ev.preventDefault(); + }, + onFormData: (ev) => { + console.log(ev); + for (let value of ev.formData.values()) { + console.log(value); } -} - - - + }, + onValidate: (ev) => { + const validations = []; + for (let prop in validators) { + validations.push( + document.querySelector(`[name="${prop}"]`).validity.valid + ); + } + if (validations.filter((val) => val == false).length) { + console.warn('INVALID'); + } else { + console.log('VALID'); + } + }, +}; diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index fd8a82d..3f3f25e 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -4,7 +4,7 @@ export class TextInputComponent extends HTMLElement { static formAssociated = true; public $validator: Validator; private internals: IElementInternals; - private $attr = {} + private $attr = {}; constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' }); @@ -69,58 +69,70 @@ export class TextInputComponent extends HTMLElement { } static get observedAttributes() { - return ["name", "type", "required","minlength", "maxlength","pattern","list","placeholder","readonly", "spellcheck", "value", "disabled"] + return [ + 'name', + 'type', + 'required', + 'minlength', + 'maxlength', + 'pattern', + 'list', + 'placeholder', + 'readonly', + 'spellcheck', + 'value', + 'disabled', + ]; } attributeChangedCallback(name, prev, next) { this.$attr[name] = next; switch (name) { - case "value": - this.value = next + case 'value': + this.value = next; break; - case "required": - this.required = next + case 'required': + this.required = next; break; - case "disabled": + case 'disabled': this.disabled = next; break; - case "type": - this.$input.setAttribute("type", next); + case 'type': + this.$input.setAttribute('type', next); break; - case "minlength": - this.$input.setAttribute("minlength", next); + case 'minlength': + this.$input.setAttribute('minlength', next); break; - case "maxlength": - this.$input.setAttribute("maxlength", next); + case 'maxlength': + this.$input.setAttribute('maxlength', next); break; - case "pattern": - this.$input.setAttribute("pattern", next); + case 'pattern': + this.$input.setAttribute('pattern', next); break; - case "list": - this.$input.setAttribute("list", next); + case 'list': + this.$input.setAttribute('list', next); break; - case "placeholder": - this.$input.setAttribute("placeholder", next); + case 'placeholder': + this.$input.setAttribute('placeholder', next); break; - case "readonly": - this.$input.setAttribute("readonly", next); - case "spellcheck": - this.$input.setAttribute("spellcheck", next); + case 'readonly': + this.$input.setAttribute('readonly', next); + case 'spellcheck': + this.$input.setAttribute('spellcheck', next); break; } } connectedCallback() { - for (let prop in this.$attr) { this.$input.setAttribute(prop, this.$attr[prop]); } - this.$input.onblur = ()=> { + this.$input.onblur = () => { this.onValidate(true); - } + }; this.onValidate(false); this.$input.onchange = () => { - this.onChange() - } + this.onChange(); + }; } formDisabledCallback(disabled) { @@ -132,7 +144,7 @@ export class TextInputComponent extends HTMLElement { } formResetCallback(state: string) { - this.value = this.getAttribute("value") || ""; + this.value = this.getAttribute('value') || ''; } checkValidity() { return this.internals.checkValidity(); @@ -142,29 +154,29 @@ export class TextInputComponent extends HTMLElement { } onValidate(showError: boolean) { - validate(this, showError) + validate(this, showError); } focus() { - this.$input.focus() + this.$input.focus(); } blur() { - this.$input.blur() + this.$input.blur(); } onChange() { - this.shadowRoot.querySelector(".message").innerHTML = "" - this.$input.classList.remove("error") - this.internals.setFormValue(this.value, this.value) + this.shadowRoot.querySelector('.message').innerHTML = ''; + this.$input.classList.remove('error'); + this.internals.setFormValue(this.value, this.value); } get type() { - return this.$input.type ?? "text"; + return this.$input.type ?? 'text'; } set type(type: string) { - this.$input.setAttribute("type" , type); + this.$input.setAttribute('type', type); } get list() { @@ -176,7 +188,7 @@ export class TextInputComponent extends HTMLElement { } set minLength(min: number) { - this.$input.minLength = min + this.$input.minLength = min; } get maxLength() { @@ -187,7 +199,7 @@ export class TextInputComponent extends HTMLElement { this.$input.maxLength = max; } - get readOnly () { + get readOnly() { return this.$input.readOnly; } @@ -200,19 +212,19 @@ export class TextInputComponent extends HTMLElement { } get placeholder() { - return this.$input.placeholder + return this.$input.placeholder; } get spellcheck() { return this.$input.spellcheck; } - set disabled (value: boolean | string) { - if (value === "true" || value === true) { - this.$input.setAttribute("disabled", "true") + set disabled(value: boolean | string) { + if (value === 'true' || value === true) { + this.$input.setAttribute('disabled', 'true'); } - if (value === "false" || value === false) { - this.$input.removeAttribute("disabled") + if (value === 'false' || value === false) { + this.$input.removeAttribute('disabled'); } } get disabled() { @@ -229,27 +241,25 @@ export class TextInputComponent extends HTMLElement { return this.shadowRoot.querySelector('input'); } - - - set value (value: string) { - this.$input.value = value + set value(value: string) { + this.$input.value = value; } get value(): string { - return this.$input.value + return this.$input.value; } set required(value: boolean | string) { - if (value === "true" || value === true) { - this.$input.setAttribute("required", "true") + if (value === 'true' || value === true) { + this.$input.setAttribute('required', 'true'); } - if (value === "false" || value == false) { - this.$input.removeAttribute("required") + if (value === 'false' || value == false) { + this.$input.removeAttribute('required'); } } get required(): boolean { - return this.$input.required + return this.$input.required; } setValidity( diff --git a/packages/component/src/input/validator.ts b/packages/component/src/input/validator.ts index 480f9f5..3de4039 100644 --- a/packages/component/src/input/validator.ts +++ b/packages/component/src/input/validator.ts @@ -1,49 +1,49 @@ export type Validator = { - validations: { - flag: ValidityStateFlags; - condition: (elem: HTMLElement) => boolean; - message?: string; - }[]; + validations: { + flag: ValidityStateFlags; + condition: (elem: HTMLElement) => boolean; + message?: string; + }[]; }; export function validate(elem: any, showError: boolean) { - if(!elem.$validator || !elem.$validator.validations) { - return; - } - - const messageElem = elem.shadowRoot.querySelector(".message") + if (!elem.$validator || !elem.$validator.validations) { + return; + } - if(messageElem) { - messageElem.innerHTML = "" - } + const messageElem = elem.shadowRoot.querySelector('.message'); - const activeValidators = []; - elem.$validator.validations.forEach((validator)=> { - if(validator.condition(elem)) { - elem.setValidity(validator.flag, validator.message); - activeValidators.push(validator) - if(showError) { - if(elem.$input) { - elem.$input.classList.add("error"); - } - if (messageElem) { - const div = document.createElement("div") - div.innerHTML = validator.message; - messageElem.appendChild(div) - } - } - } - }); + if (messageElem) { + messageElem.innerHTML = ''; + } - if(!activeValidators.length) { - elem.setValidity({}) + const activeValidators = []; + elem.$validator.validations.forEach((validator) => { + if (validator.condition(elem)) { + elem.setValidity(validator.flag, validator.message); + activeValidators.push(validator); + if (showError) { if (elem.$input) { - elem.$input.classList.remove("error") + elem.$input.classList.add('error'); } - if(messageElem) { - messageElem.innerHTML = "" + if (messageElem) { + const div = document.createElement('div'); + div.innerHTML = validator.message; + messageElem.appendChild(div); } + } + } + }); + + if (!activeValidators.length) { + elem.setValidity({}); + if (elem.$input) { + elem.$input.classList.remove('error'); + } + if (messageElem) { + messageElem.innerHTML = ''; } + } - elem.dispatchEvent(new CustomEvent("validate", {bubbles: true})); -} \ No newline at end of file + elem.dispatchEvent(new CustomEvent('validate', { bubbles: true })); +} diff --git a/packages/component/tsconfig.json b/packages/component/tsconfig.json index df8b684..d536b71 100644 --- a/packages/component/tsconfig.json +++ b/packages/component/tsconfig.json @@ -5,11 +5,6 @@ "declarationDir": "dist/types", "emitDeclarationOnly": true }, - "include": [ - "./**/*.ts" - ], - "exclude": [ - "./**/*.stories.js", - "./dist" - ] -} \ No newline at end of file + "include": ["./**/*.ts"], + "exclude": ["./**/*.stories.js", "./dist"] +} From e61967adffe89a3cb2ccf1a65a894a7123c7ee6b Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Wed, 11 Dec 2024 08:52:16 -0600 Subject: [PATCH 27/78] styling the button component --- packages/component/src/button/Button.stories.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/component/src/button/Button.stories.js b/packages/component/src/button/Button.stories.js index f00b9d7..0f57fbd 100644 --- a/packages/component/src/button/Button.stories.js +++ b/packages/component/src/button/Button.stories.js @@ -1 +1,17 @@ import { ButtonComponent } from './Button'; +import { html } from 'lit-html'; + +export default { + title: 'Components/Inputs/Button', + component: 'in-button', +}; + +const Template = ({ label, variant }) => html` + +`; + +export const Primary = Template.bind({}); +Primary.args = { + variant: 'primary', + label: 'Button', +}; From 5e0b17eec5302ee251f787fe0c8fec779c1f7585 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Thu, 12 Dec 2024 14:14:02 -0600 Subject: [PATCH 28/78] added primary button styles --- packages/component/src/button/Button.ts | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/component/src/button/Button.ts b/packages/component/src/button/Button.ts index 980c5b0..9a659d8 100644 --- a/packages/component/src/button/Button.ts +++ b/packages/component/src/button/Button.ts @@ -2,6 +2,38 @@ export class ButtonComponent extends HTMLButtonElement { constructor() { super(); } + + connectedCallback() { + this.classList.add('in-button'); + this.addStylesheet(); + } + + addStylesheet() { + const head = document.head; + if (document.getElementById(`in-button-style`)) { + return; + } + const style = document.createElement('style'); + style.setAttribute('id', `in-button-style`); + style.textContent = buttonStyles; + head.appendChild(style); + } } +const buttonStyles = ` + .in-button.primary { + background: var(--color-blue-500); + border: 2px solid var(--color-blue-500); + box-sizing: border-box; + border-radius: 12px; + min-height: 44px; + min-width: 180px; + color: var(--color-white); + font-size: var(--font-body-md); + font-weight: var(--font-weight-button); + cursor: pointer; + padding: 0px; + } + `; + customElements.define('in-button', ButtonComponent, { extends: 'button' }); From 9242989e53d0611962edd0d7195e3f7f5f0b2a9c Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Thu, 12 Dec 2024 18:56:45 -0600 Subject: [PATCH 29/78] finished icon button --- .../component/src/button/Button.stories.js | 19 +++++++++ packages/component/src/button/Button.ts | 40 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/packages/component/src/button/Button.stories.js b/packages/component/src/button/Button.stories.js index 0f57fbd..ec31ea2 100644 --- a/packages/component/src/button/Button.stories.js +++ b/packages/component/src/button/Button.stories.js @@ -1,6 +1,13 @@ import { ButtonComponent } from './Button'; import { html } from 'lit-html'; +let icon = null; + +if (window.FontAwesome) { + icon = window.FontAwesome.icon({ prefix: 'fas', iconName: 'plus' }); +} + +const svg = icon.node[0]; export default { title: 'Components/Inputs/Button', component: 'in-button', @@ -15,3 +22,15 @@ Primary.args = { variant: 'primary', label: 'Button', }; + +export const Secondary = Template.bind({}); +Secondary.args = { + variant: 'secondary', + label: 'Button', +}; + +export const Icon = Template.bind({}); +Icon.args = { + variant: 'icon icon-close', + label: svg, +}; diff --git a/packages/component/src/button/Button.ts b/packages/component/src/button/Button.ts index 9a659d8..08ce4df 100644 --- a/packages/component/src/button/Button.ts +++ b/packages/component/src/button/Button.ts @@ -34,6 +34,46 @@ const buttonStyles = ` cursor: pointer; padding: 0px; } + .in-button.secondary { + background: var(--color-blue-white); + border: 2px solid var(--color-blue-500); + box-sizing: border-box; + border-radius: 12px; + min-height: 44px; + min-width: 180px; + color: var(--color-blue-500); + font-size: var(--font-body-md); + font-weight: var(--font-weight-button); + cursor: pointer; + padding: 0px; + } + + .in-button.icon { + display: flex; + align-items: center; + justify-content: center; + background: var(--color-white); + border: 2px solid var(--color-blue-500); + box-sizing: border-box; + border-radius: 12px; + height: 44px; + width: 44px; + color: var(--color-blue-500); + font-size: var(--font-body-icon); + font-weight: var(--font-weight-button); + cursor: pointer; + padding: 0px; + padding: var(--padding-xs); + } + + .icon svg { + width: 100%; + height: 100%; + } + + .icon.icon-close svg { + transform: rotateZ(45deg); + } `; customElements.define('in-button', ButtonComponent, { extends: 'button' }); From ad8bea9681e5be0bd05506e45d132422670e44a5 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Fri, 13 Dec 2024 07:43:21 -0600 Subject: [PATCH 30/78] making the form accessible --- .../component/src/button/Button.stories.js | 10 +++++ packages/component/src/button/Button.ts | 37 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/packages/component/src/button/Button.stories.js b/packages/component/src/button/Button.stories.js index ec31ea2..b70b9a1 100644 --- a/packages/component/src/button/Button.stories.js +++ b/packages/component/src/button/Button.stories.js @@ -34,3 +34,13 @@ Icon.args = { variant: 'icon icon-close', label: svg, }; + +const DisabledTemplate = ({ label, variant }) => html` + +`; + +export const Disabled = DisabledTemplate.bind({}); +Disabled.args = { + variant: 'primary', + label: 'Submit', +}; diff --git a/packages/component/src/button/Button.ts b/packages/component/src/button/Button.ts index 08ce4df..2ac77aa 100644 --- a/packages/component/src/button/Button.ts +++ b/packages/component/src/button/Button.ts @@ -74,6 +74,43 @@ const buttonStyles = ` .icon.icon-close svg { transform: rotateZ(45deg); } + + .in-button.primary:focus, + .in-button.secondary:focus, + .in-button.icon:focus { + background: var(--color-white); + color: var(--color-black); + border: 2px solid var(--color-black); + outline: none; + } + .in-button.primary:active, + .in-button.secondary:active, + .in-button.icon:active { + background: var(--color-white); + border: 2px solid var(--color-neutral-500); + outline: none; + } + + .in-button.primary[disabled], + .in-button.secondary[disabled], + .in-button.icon[disabled] { + opacity: var(--color-disable); + background: var(--color-disable); + border: var(--border-disable); + color: var(--color-neutral-500); + cursor: default; + } + + .in-button.primary[disabled]:focus, + .in-button.secondary[disabled]:focus, + .in-button.icon[disabled]:focus, + .in-button.primary[disabled]:active, + .in-button.secondary[disabled]:active, + .in-button.icon[disabled]:active { + border: var(--border-disable); + outline: none; + box-shadow: none; + } `; customElements.define('in-button', ButtonComponent, { extends: 'button' }); From 6056fd160af5b51eb7bcb9f48331151357263da6 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sun, 15 Dec 2024 18:36:15 -0600 Subject: [PATCH 31/78] finished adding accessibility --- packages/component/src/button/Button.stories.js | 14 ++++++++++++-- packages/component/src/input/TextInput.stories.js | 4 +++- packages/component/src/input/TextInput.ts | 8 ++++++-- packages/component/src/input/validator.ts | 1 + packages/style/style.css | 4 ++++ 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/component/src/button/Button.stories.js b/packages/component/src/button/Button.stories.js index b70b9a1..0fbf9c7 100644 --- a/packages/component/src/button/Button.stories.js +++ b/packages/component/src/button/Button.stories.js @@ -8,6 +8,7 @@ if (window.FontAwesome) { } const svg = icon.node[0]; +svg.setAttribute('aria-hidden', 'true'); export default { title: 'Components/Inputs/Button', component: 'in-button', @@ -29,10 +30,19 @@ Secondary.args = { label: 'Button', }; -export const Icon = Template.bind({}); +const IconTemplate = ({ label, variant, svg }) => + html` `; +export const Icon = IconTemplate.bind({}); Icon.args = { variant: 'icon icon-close', - label: svg, + label: 'Close', + svg: svg, }; const DisabledTemplate = ({ label, variant }) => html` diff --git a/packages/component/src/input/TextInput.stories.js b/packages/component/src/input/TextInput.stories.js index c118782..f6be02d 100644 --- a/packages/component/src/input/TextInput.stories.js +++ b/packages/component/src/input/TextInput.stories.js @@ -1,4 +1,5 @@ import { TextInputComponent } from './TextInput'; +import { ButtonComponent } from '../button/Button'; import { html } from 'lit-html'; export default { @@ -134,8 +135,9 @@ const FormTemplate = ({ headline, onSubmit, onValidate, onFormData }) => { required minlength="8" pattern="^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,}$" + class="form-control" > - + `; diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 3f3f25e..da6d8be 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -60,9 +60,9 @@ export class TextInputComponent extends HTMLElement { }
- +
-
+
`; shadowRoot.appendChild(template.content.cloneNode(true)); this.internals = this.attachInternals(); @@ -129,6 +129,9 @@ export class TextInputComponent extends HTMLElement { this.$input.onblur = () => { this.onValidate(true); }; + this.$input.onkeyup = () => { + this.onChange(); + }; this.onValidate(false); this.$input.onchange = () => { this.onChange(); @@ -168,6 +171,7 @@ export class TextInputComponent extends HTMLElement { onChange() { this.shadowRoot.querySelector('.message').innerHTML = ''; this.$input.classList.remove('error'); + this.$input.removeAttribute('aria-invalid'); this.internals.setFormValue(this.value, this.value); } diff --git a/packages/component/src/input/validator.ts b/packages/component/src/input/validator.ts index 3de4039..4a74f9c 100644 --- a/packages/component/src/input/validator.ts +++ b/packages/component/src/input/validator.ts @@ -24,6 +24,7 @@ export function validate(elem: any, showError: boolean) { activeValidators.push(validator); if (showError) { if (elem.$input) { + elem.$input.setAttribute('aria-invalid', 'true'); elem.$input.classList.add('error'); } if (messageElem) { diff --git a/packages/style/style.css b/packages/style/style.css index f136198..2d20559 100644 --- a/packages/style/style.css +++ b/packages/style/style.css @@ -177,3 +177,7 @@ label { margin-bottom: var(--margin-sm); } +.form-control { + margin-bottom: var(--margin-md); +} + From ccf1411c673c4025cb95fff6b178ba38743abab4 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sun, 15 Dec 2024 19:03:01 -0600 Subject: [PATCH 32/78] finished chapter 3 --- cypress/e2e/TextInput.cy.js | 4 ++-- ...mponents-inputs-button-disabled-1-snap.png | Bin 0 -> 5298 bytes ...s-components-inputs-button-icon-1-snap.png | Bin 0 -> 4263 bytes ...omponents-inputs-button-primary-1-snap.png | Bin 0 -> 5043 bytes ...ponents-inputs-button-secondary-1-snap.png | Bin 0 -> 5293 bytes ...mponents-inputs-text-input-form-1-snap.png | Bin 10570 -> 11035 bytes .../component/src/button/Button.stories.js | 5 +++-- 7 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 packages/component/packages/component/src/button/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-button-disabled-1-snap.png create mode 100644 packages/component/packages/component/src/button/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-button-icon-1-snap.png create mode 100644 packages/component/packages/component/src/button/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-button-primary-1-snap.png create mode 100644 packages/component/packages/component/src/button/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-button-secondary-1-snap.png diff --git a/cypress/e2e/TextInput.cy.js b/cypress/e2e/TextInput.cy.js index 0988686..ac20b5a 100644 --- a/cypress/e2e/TextInput.cy.js +++ b/cypress/e2e/TextInput.cy.js @@ -3,7 +3,7 @@ describe('TextInputComponent', () => { cy.visit('iframe.html?id=components-inputs-textinput--form'); cy.get('#root').get('[id="username"]').should('be.visible').click(); cy.get('#root').get('[id="password"]').should('be.visible').click(); - cy.get('#root').get('.submit').should('be.visible').click(); + cy.get('#root').get('.primary').should('be.visible').click(); cy.get('#root') .get('[id="username"]') .shadow() @@ -29,7 +29,7 @@ describe('TextInputComponent', () => { .shadow() .find('input') .type('W3BC0mpon3nts!'); - cy.get('#root').get('.submit').should('be.visible').click(); + cy.get('#root').get('.primary').should('be.visible').click(); cy.get('#root') .get('[id="username"]') .shadow() diff --git a/packages/component/packages/component/src/button/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-button-disabled-1-snap.png b/packages/component/packages/component/src/button/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-button-disabled-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..b95f1dd257c5f55449e652ccfced4d8053509213 GIT binary patch literal 5298 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 Lh92V{jlcX4TTVX( literal 0 HcmV?d00001 diff --git a/packages/component/packages/component/src/button/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-button-icon-1-snap.png b/packages/component/packages/component/src/button/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-button-icon-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..be814034ffa5764201d80a0c972f7bc0308bcd5f GIT binary patch literal 4263 zcmeHK>r+x`9DdQZtfpvdO*B!fDR;}wq0CGY&Cw-mSF>94Qfg9}i3yqpir`o++em6V znIWtn*tctfQhBL;$6sk0h@b!S3?4xXU#G=sR* zpH%VLG;g*ubdE$eCi9)qYxf*rZ0ISpz_ByY`L?%uUO%TL*yK z)&OYY02BbbZI%Jh^*P3u$wa!2SSWsMq;T+Pk-Q&EN;Y12nuwS%iJ>>Cqcyli(-_7< z>LQtgiP`B1sqmW0CuAKExyKby^%Ko?rZn$i7X-O-%?^NSZojQkdKEXcM2^;BNYS_C zKK`Q7eIhw6C;EPAuXG9%GklY(RU};>oqDF$T2dh6O*?F$Cp*ekIo5Za!NG|-(@F2z zygP|W$=MuTv{f&t<&KEF9PX-#Ee@#kKVbOFtkVnrCkm;zaXee&yZF z%qm9|$UTSk4RG;uL1bq2tR$KJWWW@$XRyUz0 zUU%vD0WusRBBF66+)AYE4_hS*->dCTb^dgin7CJg_TPnH0YKaMTHy+1NG`dJDc^}L ze@l*0bW7px>RO^I^7e{M?!2C)@n50uP&2@x_4KSuylCaZ_E8tJPpn3nmls4+> zvxM~4yBh!~?MXmQn^I01gS+&)`r##8II+}v&`eL^^t!Va1gfoPh4Vf+X?|g+Va>7R zde9Fy_yj#ySQHbdb#!M$j_kEXtHW%RLjv}bH?N~4=Z9f?9uu!n4Fk{Wr7LV} z&l|THe}e5BBpcnXxYj0KBd3Hl-rNic9iPM⪙z0tV}Wl$afCk% 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 D;!sbV literal 0 HcmV?d00001 diff --git a/packages/component/packages/component/src/input/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-text-input-form-1-snap.png b/packages/component/packages/component/src/input/__snapshots__/web-components-storyshots-test-js-storyshots-components-inputs-text-input-form-1-snap.png index 3a7888c20b849709e42ed53380de33ca0873e2ac..d24dc9da638d78c6c09ffd392dd38e5aca43a2d2 100644 GIT binary patch literal 11035 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 literal 10570 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

()UiVdL)ZemrO-T{Bg? z^mP(^mR(iI)LVqJK~iTJ`JJ+3seR05fsG(=nl^1gCRA6(LTC^N)InwPp| zpuskjw(fpR$uFzE-fUCq_T+EYR1Y~N{mW;O0)&Y4PeTDs@A9tCnZDNiY;j!g%DYFI zcRYJgSW4(j--EypFWdgIvHBgVHGEGZv9k>(LXXCP4^p~7NlB;3!`erjAp3xF!)c#z z(lSs?LJ!uFh@` zrCBYiWKZLqE<&jg=_3SV9Ca9O#PyNz@Oi_r2ruB?rPS)W2hPNy2O}|Sqf^t>enIU$^e<`$4U?GVLYdQ&ikvvwwl)=?e$+ z$(q_);I@7?5(w?IRJjYWgQ2-}F_F5)h0J$k1Qd=Fa~v|ER!ei?o3>Q~5E3Yq!s)9Z znYj=IWrvTE1Y)i^6|(&aRbGUpbD3KPPyuHmixBHUWxzZG8Fo0DCc<@a5CEWT%(ozY zni9hzzIw!x&j)TorUt|}r}lERJOyXE%w^({;P#^#W-*ZsAU-s(AR&?aAl+ctlMkU=eL4HIH!T#;SoL-`gvm!6?i zR#z9)*49oiltC0fj8#kmrq&0U4a23B94VT<)TTw0@cT8f(lxToFj>R44U#IYaw_C$ z2uqzCY?v-8u7G5YjYRU$HK`E7!5~5DeWRkeNxWL*W#qNKzCO3mUMCDh8i*wEfdK=3 zzGjAkMn-DO6NU^70%jcR|*9Da&k^u{j3iLcv-7l0;9kV7>}hwkik)xeo$X3w2wKA zaKSU4w-CGQO}nE<5f-6vkn6UZ1d=-G$sCZIw{po-FN=`8516apDyTY=#BlJs*u(K5;NZ38H*d3|%sy#W!%`r#L}LM-9f#GS1?w(L)b=B> z8Dw7lT;EvG6_$t{LAQc#%Mc1ndj_QW%T-lXX5#@231pBO*ro*4tna)5r&u?k5-b!= z^&ydHTXeTh1)KiaI`UnBW_9XtQ0-9}R6`ofCp3{^A`%JU>ZhHMxRp|>d87RNlfU6S zNIukEZAm4mEc!-!r)(j!u{@z`Bx=e?%o5E6jMi+KN2NN8yNx;k*U2?3UjtTPsZ zMy^wNq*IsC_-z#!3?UL3iP6N9mgZ-mx)Hx)AG?$+__&vmUg%ITfef$5pqSQ_@SsxL z5nlz9io?jLP8+NZ8Vhe?sXNNVv2TCbvTNxkuI_Khv;`U142c1ZF2+wshKEcQaxbmU z4hmqJA*~x520`M}p1Ki$Ap_tU<>LWX&~&RX&%#ThL2Dr3jucz34gC-3C?x> zyKhvQTQC+8&hOa9$WS-n;u{@hqi@EW6Uklu3W{pkKuqS`8IZzGs$u*zFzdRYAv5nF zgM#yS+ZRBap$$Gu0wnJL4_F201&8K1f4IT820Vopt^=Mca^PbpH?nL**h2n!{^&$y zdpZo~5pOc&S1>nQ2v-_(UjtEm3(-bfAUpZT(DpygcQc@u|8IZ!?ynN%Km=w+P?wZI}k Date: Tue, 17 Dec 2024 20:12:33 -0600 Subject: [PATCH 33/78] built the component decorator --- packages/common/src/decorator/component.ts | 25 ++++++++++++++++++++++ packages/common/src/decorator/index.ts | 0 2 files changed, 25 insertions(+) create mode 100644 packages/common/src/decorator/component.ts create mode 100644 packages/common/src/decorator/index.ts diff --git a/packages/common/src/decorator/component.ts b/packages/common/src/decorator/component.ts new file mode 100644 index 0000000..863d668 --- /dev/null +++ b/packages/common/src/decorator/component.ts @@ -0,0 +1,25 @@ +export interface ElementMeta { + selector?: string; + style?: string; + template?: string; +} + +export function Component(meta: ElementMeta) { + if (!meta) { + console.error('Component must include ElementMeta to compile'); + return; + } + return (target: any) => { + if (!meta.style) { + meta.style = ''; + } + if (!meta.template) { + meta.template = ''; + } + target.prototype.elementMeta = meta; + if (meta.selector) { + customElements.define(meta.selector, target); + } + return target; + }; +} diff --git a/packages/common/src/decorator/index.ts b/packages/common/src/decorator/index.ts new file mode 100644 index 0000000..e69de29 From 783953733259af7d8c5ebe1b5ee35e5d84db4d88 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Thu, 19 Dec 2024 10:24:21 -0600 Subject: [PATCH 34/78] building out monorepo - page 211 --- lerna.json | 7 ++----- packages/common/index.ts | 3 +++ packages/common/src/decorator/index.ts | 2 ++ packages/common/src/template/index.ts | 1 + packages/common/src/template/shadow.ts | 1 + 5 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 packages/common/src/template/index.ts create mode 100644 packages/common/src/template/shadow.ts diff --git a/lerna.json b/lerna.json index c36ae21..82cca82 100644 --- a/lerna.json +++ b/lerna.json @@ -1,11 +1,8 @@ { "version": "0.0.1", "npmClient": "yarn", - "useWorkspaces": true, - "packages": [ - "packages/*" - ], + "packages": ["packages/*"], "publish": { "contents": "dist" } -} \ No newline at end of file +} diff --git a/packages/common/index.ts b/packages/common/index.ts index e69de29..3d65b06 100644 --- a/packages/common/index.ts +++ b/packages/common/index.ts @@ -0,0 +1,3 @@ +export { Component } from './src/decorator'; +export type { ElementMeta } from './src/decorator'; +export { attachShadow } from './src/template'; diff --git a/packages/common/src/decorator/index.ts b/packages/common/src/decorator/index.ts index e69de29..761d0c8 100644 --- a/packages/common/src/decorator/index.ts +++ b/packages/common/src/decorator/index.ts @@ -0,0 +1,2 @@ +export { Component } from './component'; +export type { ElementMeta } from './component'; diff --git a/packages/common/src/template/index.ts b/packages/common/src/template/index.ts new file mode 100644 index 0000000..4ebf1f8 --- /dev/null +++ b/packages/common/src/template/index.ts @@ -0,0 +1 @@ +export { attachShadow } from './shadow'; diff --git a/packages/common/src/template/shadow.ts b/packages/common/src/template/shadow.ts new file mode 100644 index 0000000..17e9c37 --- /dev/null +++ b/packages/common/src/template/shadow.ts @@ -0,0 +1 @@ +export function attachShadow(context: any, options?: ShadowRootInit) {} From 96e86f4baa86c181630255d0ab6b88d7d6bf0d87 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Thu, 19 Dec 2024 18:40:55 -0600 Subject: [PATCH 35/78] built decorator pattern, Refactor is next --- packages/common/src/template/shadow.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/common/src/template/shadow.ts b/packages/common/src/template/shadow.ts index 17e9c37..d5dcf1d 100644 --- a/packages/common/src/template/shadow.ts +++ b/packages/common/src/template/shadow.ts @@ -1 +1,12 @@ -export function attachShadow(context: any, options?: ShadowRootInit) {} +export function attachShadow(context: any, options?: ShadowRootInit) { + const shadowRoot: ShadowRoot = context.attachShadow( + options || { mode: 'open' } + ); + const template = document.createElement('template'); + template.innerHTML = ` + + ${context.elementMeta.template} + `; + + shadowRoot.appendChild(template.content.cloneNode(true)); +} From c786a125291bf886c49c0415c239979fb1cd8747 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Fri, 20 Dec 2024 14:35:08 -0600 Subject: [PATCH 36/78] refactored card and input components page - 219 --- packages/component/src/card/Card.ts | 46 +++++++++++------------ packages/component/src/input/TextInput.ts | 46 ++++++++++++----------- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/packages/component/src/card/Card.ts b/packages/component/src/card/Card.ts index 42a69a1..2588d84 100644 --- a/packages/component/src/card/Card.ts +++ b/packages/component/src/card/Card.ts @@ -1,13 +1,8 @@ -export class CardComponent extends HTMLElement { - constructor() { - super(); - - const shadowRoot = this.attachShadow({ mode: 'open' }); - - const template = document.createElement('template'); - template.innerHTML = ` - -

- -
-
- -
-
- -
- `; - shadowRoot.appendChild(template.content.cloneNode(true)); + `, + template: ` +
+ +
+
+ +
+
+ +
+ `, +}) +export class CardComponent extends HTMLElement { + constructor() { + super(); + attachShadow(this); } } - -customElements.define('in-card', CardComponent); diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index da6d8be..d5a7fac 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -1,18 +1,11 @@ import { IElementInternals } from 'types/lib.elementInternals'; import { Validator, validate } from './validator'; -export class TextInputComponent extends HTMLElement { - static formAssociated = true; - public $validator: Validator; - private internals: IElementInternals; - private $attr = {}; - constructor() { - super(); - const shadowRoot = this.attachShadow({ mode: 'open' }); - const template = document.createElement('template'); +import { Component, attachShadow } from '@in/common'; - template.innerHTML = ` - -
- -
-
- `; - shadowRoot.appendChild(template.content.cloneNode(true)); + }`, + template: `
+ +
+
`, +}) +export class TextInputComponent extends HTMLElement { + static formAssociated = true; + public $validator: Validator; + private internals: IElementInternals; + private $attr = {}; + constructor() { + super(); + attachShadow(this); this.internals = this.attachInternals(); } @@ -274,5 +278,3 @@ export class TextInputComponent extends HTMLElement { this.internals.setValidity(flags, message, anchor); } } - -customElements.define('in-textinput', TextInputComponent); From aa6424ee6227e3b14ffc715ebac895c614535bcb Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sat, 21 Dec 2024 09:58:28 -0600 Subject: [PATCH 37/78] rebuilt the package, no on to refactoring the button component --- packages/common/index.ts | 2 +- packages/common/src/decorator/component.ts | 5 ++++- packages/common/src/template/index.ts | 1 + packages/common/src/template/style.ts | 23 ++++++++++++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 packages/common/src/template/style.ts diff --git a/packages/common/index.ts b/packages/common/index.ts index 3d65b06..ef9c9e9 100644 --- a/packages/common/index.ts +++ b/packages/common/index.ts @@ -1,3 +1,3 @@ export { Component } from './src/decorator'; export type { ElementMeta } from './src/decorator'; -export { attachShadow } from './src/template'; +export { attachShadow, attachStyle } from './src/template'; diff --git a/packages/common/src/decorator/component.ts b/packages/common/src/decorator/component.ts index 863d668..507c4ae 100644 --- a/packages/common/src/decorator/component.ts +++ b/packages/common/src/decorator/component.ts @@ -1,4 +1,5 @@ export interface ElementMeta { + custom?: ElementDefinitionOptions; selector?: string; style?: string; template?: string; @@ -17,8 +18,10 @@ export function Component(meta: ElementMeta) { meta.template = ''; } target.prototype.elementMeta = meta; - if (meta.selector) { + if (meta.selector && !meta.custom) { customElements.define(meta.selector, target); + } else if (meta.selector && meta.custom) { + customElements.define(meta.selector, target, meta.custom); } return target; }; diff --git a/packages/common/src/template/index.ts b/packages/common/src/template/index.ts index 4ebf1f8..e93d810 100644 --- a/packages/common/src/template/index.ts +++ b/packages/common/src/template/index.ts @@ -1 +1,2 @@ export { attachShadow } from './shadow'; +export { attachStyle } from './style'; diff --git a/packages/common/src/template/style.ts b/packages/common/src/template/style.ts new file mode 100644 index 0000000..9895a8e --- /dev/null +++ b/packages/common/src/template/style.ts @@ -0,0 +1,23 @@ +function closestRoot(base: Element): any { + if (base.getRootNode() === document) { + return document.head; + } else if (base.getRootNode()) { + return base.getRootNode(); + } else { + return document.head; + } +} +export function attachStyle(context: any): void { + const id = `${context.elementMeta.selector}`; + const closest = closestRoot(context); + if (closest.tagName === 'HEAD' && closest.getElementById(`${id}-in-style`)) { + return; + } + if (closest.getElementById && closest.getElementById(`${id}-in-style`)) { + return; + } + const template = document.createElement('style'); + template.setAttribute('id', `${id}-in-style`); + template.innerText = context.elementMeta.style; + closest.appendChild(template); +} From 8906a02c3119826596fbc853800bb257bb96f354 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sun, 22 Dec 2024 10:09:51 -0600 Subject: [PATCH 38/78] coding a generic template page-228 --- packages/common/src/template/style.ts | 2 +- packages/component/src/button/Button.ts | 37 ++++++++++--------------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/packages/common/src/template/style.ts b/packages/common/src/template/style.ts index 9895a8e..8d8297f 100644 --- a/packages/common/src/template/style.ts +++ b/packages/common/src/template/style.ts @@ -10,7 +10,7 @@ function closestRoot(base: Element): any { export function attachStyle(context: any): void { const id = `${context.elementMeta.selector}`; const closest = closestRoot(context); - if (closest.tagName === 'HEAD' && closest.getElementById(`${id}-in-style`)) { + if (closest.tagName === 'HEAD' && document.getElementById(`${id}-in-style`)) { return; } if (closest.getElementById && closest.getElementById(`${id}-in-style`)) { diff --git a/packages/component/src/button/Button.ts b/packages/component/src/button/Button.ts index 2ac77aa..fa8b7e3 100644 --- a/packages/component/src/button/Button.ts +++ b/packages/component/src/button/Button.ts @@ -1,24 +1,4 @@ -export class ButtonComponent extends HTMLButtonElement { - constructor() { - super(); - } - - connectedCallback() { - this.classList.add('in-button'); - this.addStylesheet(); - } - - addStylesheet() { - const head = document.head; - if (document.getElementById(`in-button-style`)) { - return; - } - const style = document.createElement('style'); - style.setAttribute('id', `in-button-style`); - style.textContent = buttonStyles; - head.appendChild(style); - } -} +import { attachStyle, Component } from '@in/common'; const buttonStyles = ` .in-button.primary { @@ -112,5 +92,18 @@ const buttonStyles = ` box-shadow: none; } `; +@Component({ + custom: { extends: 'button' }, + selector: 'in-button', + style: buttonStyles, +}) +export class ButtonComponent extends HTMLButtonElement { + constructor() { + super(); + } -customElements.define('in-button', ButtonComponent, { extends: 'button' }); + connectedCallback() { + this.classList.add('in-button'); + attachStyle(this); + } +} From 134957c73d706adf41103b4f43a0c2ea00737f5f Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Mon, 23 Dec 2024 18:32:35 -0600 Subject: [PATCH 39/78] added css and html syntax highlight --- packages/common/index.ts | 8 +- packages/common/src/template/index.ts | 1 + packages/common/src/template/template.ts | 21 +++ packages/component/src/button/Button.ts | 174 +++++++++++----------- packages/component/src/card/Card.ts | 54 +++---- packages/component/src/input/TextInput.ts | 99 ++++++------ 6 files changed, 193 insertions(+), 164 deletions(-) create mode 100644 packages/common/src/template/template.ts diff --git a/packages/common/index.ts b/packages/common/index.ts index ef9c9e9..35db4cb 100644 --- a/packages/common/index.ts +++ b/packages/common/index.ts @@ -1,3 +1,9 @@ export { Component } from './src/decorator'; export type { ElementMeta } from './src/decorator'; -export { attachShadow, attachStyle } from './src/template'; +export { + attachShadow, + attachStyle, + attachTemplate, + html, + css, +} from './src/template'; diff --git a/packages/common/src/template/index.ts b/packages/common/src/template/index.ts index e93d810..ad04eca 100644 --- a/packages/common/src/template/index.ts +++ b/packages/common/src/template/index.ts @@ -1,2 +1,3 @@ export { attachShadow } from './shadow'; export { attachStyle } from './style'; +export { attachTemplate, html, css } from './template'; diff --git a/packages/common/src/template/template.ts b/packages/common/src/template/template.ts new file mode 100644 index 0000000..280fc74 --- /dev/null +++ b/packages/common/src/template/template.ts @@ -0,0 +1,21 @@ +export function attachTemplate(context: any): void { + const template = document.createElement('template'); + template.innerHTML = context.elementMeta.template; + context.appendChild(template.content.cloneNode(true)); +} + +export function html(template: TemplateStringsArray, ...rest: any): string { + let str = ''; + template.forEach((string, i) => { + str += `${string} ${rest[i] || ''}`; + }); + return str; +} + +export function css(template: TemplateStringsArray, ...rest: any): string { + let str = ''; + template.forEach((string, i) => { + str += `${string} ${rest[i] || ''}`; + }); + return str; +} diff --git a/packages/component/src/button/Button.ts b/packages/component/src/button/Button.ts index fa8b7e3..3723070 100644 --- a/packages/component/src/button/Button.ts +++ b/packages/component/src/button/Button.ts @@ -1,97 +1,97 @@ -import { attachStyle, Component } from '@in/common'; +import { attachStyle, Component, html, css } from '@in/common'; -const buttonStyles = ` - .in-button.primary { - background: var(--color-blue-500); - border: 2px solid var(--color-blue-500); - box-sizing: border-box; - border-radius: 12px; - min-height: 44px; - min-width: 180px; - color: var(--color-white); - font-size: var(--font-body-md); - font-weight: var(--font-weight-button); - cursor: pointer; - padding: 0px; - } - .in-button.secondary { - background: var(--color-blue-white); - border: 2px solid var(--color-blue-500); - box-sizing: border-box; - border-radius: 12px; - min-height: 44px; - min-width: 180px; - color: var(--color-blue-500); - font-size: var(--font-body-md); - font-weight: var(--font-weight-button); - cursor: pointer; - padding: 0px; - } +const buttonStyles = css` + .in-button.primary { + background: var(--color-blue-500); + border: 2px solid var(--color-blue-500); + box-sizing: border-box; + border-radius: 12px; + min-height: 44px; + min-width: 180px; + color: var(--color-white); + font-size: var(--font-body-md); + font-weight: var(--font-weight-button); + cursor: pointer; + padding: 0px; + } + .in-button.secondary { + background: var(--color-blue-white); + border: 2px solid var(--color-blue-500); + box-sizing: border-box; + border-radius: 12px; + min-height: 44px; + min-width: 180px; + color: var(--color-blue-500); + font-size: var(--font-body-md); + font-weight: var(--font-weight-button); + cursor: pointer; + padding: 0px; + } - .in-button.icon { - display: flex; - align-items: center; - justify-content: center; - background: var(--color-white); - border: 2px solid var(--color-blue-500); - box-sizing: border-box; - border-radius: 12px; - height: 44px; - width: 44px; - color: var(--color-blue-500); - font-size: var(--font-body-icon); - font-weight: var(--font-weight-button); - cursor: pointer; - padding: 0px; - padding: var(--padding-xs); - } + .in-button.icon { + display: flex; + align-items: center; + justify-content: center; + background: var(--color-white); + border: 2px solid var(--color-blue-500); + box-sizing: border-box; + border-radius: 12px; + height: 44px; + width: 44px; + color: var(--color-blue-500); + font-size: var(--font-body-icon); + font-weight: var(--font-weight-button); + cursor: pointer; + padding: 0px; + padding: var(--padding-xs); + } - .icon svg { - width: 100%; - height: 100%; - } + .icon svg { + width: 100%; + height: 100%; + } - .icon.icon-close svg { - transform: rotateZ(45deg); - } + .icon.icon-close svg { + transform: rotateZ(45deg); + } - .in-button.primary:focus, - .in-button.secondary:focus, - .in-button.icon:focus { - background: var(--color-white); - color: var(--color-black); - border: 2px solid var(--color-black); - outline: none; - } - .in-button.primary:active, - .in-button.secondary:active, - .in-button.icon:active { - background: var(--color-white); - border: 2px solid var(--color-neutral-500); - outline: none; - } + .in-button.primary:focus, + .in-button.secondary:focus, + .in-button.icon:focus { + background: var(--color-white); + color: var(--color-black); + border: 2px solid var(--color-black); + outline: none; + } + .in-button.primary:active, + .in-button.secondary:active, + .in-button.icon:active { + background: var(--color-white); + border: 2px solid var(--color-neutral-500); + outline: none; + } - .in-button.primary[disabled], - .in-button.secondary[disabled], - .in-button.icon[disabled] { - opacity: var(--color-disable); - background: var(--color-disable); - border: var(--border-disable); - color: var(--color-neutral-500); - cursor: default; - } + .in-button.primary[disabled], + .in-button.secondary[disabled], + .in-button.icon[disabled] { + opacity: var(--color-disable); + background: var(--color-disable); + border: var(--border-disable); + color: var(--color-neutral-500); + cursor: default; + } - .in-button.primary[disabled]:focus, - .in-button.secondary[disabled]:focus, - .in-button.icon[disabled]:focus, - .in-button.primary[disabled]:active, - .in-button.secondary[disabled]:active, - .in-button.icon[disabled]:active { - border: var(--border-disable); - outline: none; - box-shadow: none; - } - `; + .in-button.primary[disabled]:focus, + .in-button.secondary[disabled]:focus, + .in-button.icon[disabled]:focus, + .in-button.primary[disabled]:active, + .in-button.secondary[disabled]:active, + .in-button.icon[disabled]:active { + border: var(--border-disable); + outline: none; + box-shadow: none; + } +`; @Component({ custom: { extends: 'button' }, selector: 'in-button', diff --git a/packages/component/src/card/Card.ts b/packages/component/src/card/Card.ts index 2588d84..a229177 100644 --- a/packages/component/src/card/Card.ts +++ b/packages/component/src/card/Card.ts @@ -1,33 +1,33 @@ -import { Component, attachShadow } from '@in/common'; +import { Component, attachShadow, html, css } from '@in/common'; @Component({ selector: 'in-card', - style: ` - :host{ - display: block; - background: var(--color-white); - border-radius: var(--radius-md); - box-shadow: var(--shadow); - overflow: hidden; - max-width: 320px; - } - ::slotted(*) { - padding-left: var(--padding-lg); - padding-right: var(--padding-lg); - } - ::slotted(a:link), - ::slotted(a:visited) { - display: block; - } - ::slotted(:last-child) { - padding-bottom: var(--margin-lg); - } - ::slotted(img) { - width: 100%; - padding-left: 0px; - padding-right: 0px; - } + style: css` + :host { + display: block; + background: var(--color-white); + border-radius: var(--radius-md); + box-shadow: var(--shadow); + overflow: hidden; + max-width: 320px; + } + ::slotted(*) { + padding-left: var(--padding-lg); + padding-right: var(--padding-lg); + } + ::slotted(a:link), + ::slotted(a:visited) { + display: block; + } + ::slotted(:last-child) { + padding-bottom: var(--margin-lg); + } + ::slotted(img) { + width: 100%; + padding-left: 0px; + padding-right: 0px; + } `, - template: ` + template: html`
diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index d5a7fac..582e3e2 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -1,57 +1,58 @@ import { IElementInternals } from 'types/lib.elementInternals'; import { Validator, validate } from './validator'; -import { Component, attachShadow } from '@in/common'; +import { Component, attachShadow, html, css } from '@in/common'; @Component({ selector: 'in-textinput', - style: ` - :host { - display: block; - font-family: var(--font-default); - font-size: var(--font-body-sm); - } - input { - height: var(--input-min-dimension); - width: 100%; - border-radius: var(--radius-sm); - border: var(--border-default); - font-size: var(--font-body-md); - padding-left: var(--padding-sm); - outline: none; - box-sizing: border-box; - } - input:focus, - input:focus:hover, - input:active { - border: var(--border-focus); - } - input.error, - input.error:hover, - input.error:focus, - input.error:active { - border: var(--border-error); - outline: none; - box-shadow: none; - color: var(--color-error); - } - input[disabled] { - opacity: var(--color-disable); - background: var(--color-disable); - border: var(--border-disable); - } - input[disabled]:hover, - input[disabled]:focus, - input[disabled]:active { - border: var(--border-disable); - outline: none; - box-shadow: none; - } - .message { - margin-top: var(--margin-xxs); - color: var(--color-error); - font-weight: var(--font-weight-default); - }`, - template: `
+ style: css` + :host { + display: block; + font-family: var(--font-default); + font-size: var(--font-body-sm); + } + input { + height: var(--input-min-dimension); + width: 100%; + border-radius: var(--radius-sm); + border: var(--border-default); + font-size: var(--font-body-md); + padding-left: var(--padding-sm); + outline: none; + box-sizing: border-box; + } + input:focus, + input:focus:hover, + input:active { + border: var(--border-focus); + } + input.error, + input.error:hover, + input.error:focus, + input.error:active { + border: var(--border-error); + outline: none; + box-shadow: none; + color: var(--color-error); + } + input[disabled] { + opacity: var(--color-disable); + background: var(--color-disable); + border: var(--border-disable); + } + input[disabled]:hover, + input[disabled]:focus, + input[disabled]:active { + border: var(--border-disable); + outline: none; + box-shadow: none; + } + .message { + margin-top: var(--margin-xxs); + color: var(--color-error); + font-weight: var(--font-weight-default); + } + `, + template: html`
Date: Tue, 24 Dec 2024 20:50:32 -0600 Subject: [PATCH 40/78] started listen.ts page - 241 --- packages/common/src/event/listen.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 packages/common/src/event/listen.ts diff --git a/packages/common/src/event/listen.ts b/packages/common/src/event/listen.ts new file mode 100644 index 0000000..596d5a7 --- /dev/null +++ b/packages/common/src/event/listen.ts @@ -0,0 +1,19 @@ +type MethodDecoratorFactoryFunction = ( + target: any, + key: string | number, + descriptor: PropertyDescriptor +) => void; + +export function Listen( + eventName: string, + selector?: string +): MethodDecoratorFactoryFunction { + return function decorator( + target: any, + key: string | number, + descriptor: PropertyDescriptor + ) { + const { connectedCallback = () => {}, disconnectedCallback = () => {} } = + target; + }; +} From 24809c1e0bc6c738ee56a3609f35ba1e18609091 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sat, 28 Dec 2024 16:36:57 -0600 Subject: [PATCH 41/78] finshed listner function for library --- packages/common/index.ts | 1 + packages/common/src/event/index.ts | 1 + packages/common/src/event/listen.ts | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 packages/common/src/event/index.ts diff --git a/packages/common/index.ts b/packages/common/index.ts index 35db4cb..b2154e8 100644 --- a/packages/common/index.ts +++ b/packages/common/index.ts @@ -7,3 +7,4 @@ export { html, css, } from './src/template'; +export { Listen } from './src/event'; diff --git a/packages/common/src/event/index.ts b/packages/common/src/event/index.ts new file mode 100644 index 0000000..562114c --- /dev/null +++ b/packages/common/src/event/index.ts @@ -0,0 +1 @@ +export { Listen } from './listen'; diff --git a/packages/common/src/event/listen.ts b/packages/common/src/event/listen.ts index 596d5a7..4d6b7d1 100644 --- a/packages/common/src/event/listen.ts +++ b/packages/common/src/event/listen.ts @@ -15,5 +15,27 @@ export function Listen( ) { const { connectedCallback = () => {}, disconnectedCallback = () => {} } = target; + const symbolMethod = Symbol(key); + function getContext(context) { + const root = context.shadowRoot ? context.shadowRoot : context; + return selector ? root.querySelector(selector) : context; + } + function addListener() { + const handler = (this[symbolMethod] = (...args) => { + descriptor.value.apply(this, args); + }); + getContext(this).addEventListener(eventName, handler); + } + function removeListener() { + getContext(this).removeListener(eventName, this[symbolMethod]); + } + target.connectedCallback = function connectedCallbackWrapper() { + connectedCallback.call(this); + addListener.call(this); + }; + target.disconnectedCallback = function disconnectedCallbackWrapper() { + disconnectedCallback.call(this); + removeListener.call(this); + }; }; } From ee436bc7a9a5f73a4a8b25ef22ecf4a979973a26 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Wed, 1 Jan 2025 14:42:49 -0600 Subject: [PATCH 42/78] finished chapter 4, starting on table component --- packages/component/src/input/TextInput.ts | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/packages/component/src/input/TextInput.ts b/packages/component/src/input/TextInput.ts index 582e3e2..6a0a765 100644 --- a/packages/component/src/input/TextInput.ts +++ b/packages/component/src/input/TextInput.ts @@ -1,6 +1,6 @@ import { IElementInternals } from 'types/lib.elementInternals'; import { Validator, validate } from './validator'; -import { Component, attachShadow, html, css } from '@in/common'; +import { Component, attachShadow, html, css, Listen } from '@in/common'; @Component({ selector: 'in-textinput', @@ -131,16 +131,8 @@ export class TextInputComponent extends HTMLElement { for (let prop in this.$attr) { this.$input.setAttribute(prop, this.$attr[prop]); } - this.$input.onblur = () => { - this.onValidate(true); - }; - this.$input.onkeyup = () => { - this.onChange(); - }; - this.onValidate(false); - this.$input.onchange = () => { - this.onChange(); - }; + + validate(this, false); } formDisabledCallback(disabled) { @@ -160,9 +152,9 @@ export class TextInputComponent extends HTMLElement { reportValidity() { return this.internals.reportValidity(); } - - onValidate(showError: boolean) { - validate(this, showError); + @Listen('blur', 'input') + onValidate() { + validate(this, true); } focus() { @@ -172,7 +164,8 @@ export class TextInputComponent extends HTMLElement { blur() { this.$input.blur(); } - + @Listen('change', 'input') + @Listen('keyup', 'input') onChange() { this.shadowRoot.querySelector('.message').innerHTML = ''; this.$input.classList.remove('error'); From 2cc89740085a59c237e83aef6611c3a7e31c1861 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Fri, 17 Jan 2025 08:59:10 -0600 Subject: [PATCH 43/78] fixed bug --- packages/common/src/event/listen.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/src/event/listen.ts b/packages/common/src/event/listen.ts index 4d6b7d1..7800dd6 100644 --- a/packages/common/src/event/listen.ts +++ b/packages/common/src/event/listen.ts @@ -27,7 +27,7 @@ export function Listen( getContext(this).addEventListener(eventName, handler); } function removeListener() { - getContext(this).removeListener(eventName, this[symbolMethod]); + getContext(this).removeEventListener(eventName, this[symbolMethod]); } target.connectedCallback = function connectedCallbackWrapper() { connectedCallback.call(this); From 2ea7411f7421b6a2720c7de6ec2067fd9dfd5758 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sat, 18 Jan 2025 12:02:54 -0600 Subject: [PATCH 44/78] Created table story --- packages/component/src/table/Table.stories.js | 14 ++++++++++++++ packages/component/src/table/TableCard.ts | 13 +++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 packages/component/src/table/Table.stories.js create mode 100644 packages/component/src/table/TableCard.ts diff --git a/packages/component/src/table/Table.stories.js b/packages/component/src/table/Table.stories.js new file mode 100644 index 0000000..79bc92e --- /dev/null +++ b/packages/component/src/table/Table.stories.js @@ -0,0 +1,14 @@ +import { html } from 'lit-html'; +import { TableCardComponent } from './TableCard'; + +export default { + title: 'Components/Table', + component: 'in-tablecard', +}; + +const Template = () => { + return html``; +}; + +export const Primary = Template.bind({}); +Primary.args = {}; diff --git a/packages/component/src/table/TableCard.ts b/packages/component/src/table/TableCard.ts new file mode 100644 index 0000000..6e532c4 --- /dev/null +++ b/packages/component/src/table/TableCard.ts @@ -0,0 +1,13 @@ +import { Component, attachShadow, html, css } from '@in/common'; + +@Component({ + selector: 'in-tablecard', + style: css``, + template: html``, +}) +export class TableCardComponent extends HTMLElement { + constructor() { + super(); + attachShadow(this); + } +} From 980e48b408d179662c688bdaeaa696e121c4ad02 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sat, 18 Jan 2025 12:27:27 -0600 Subject: [PATCH 45/78] coding compound components --- packages/component/src/table/Table.stories.js | 89 ++++++++++++++++++- packages/component/src/table/Table.ts | 27 ++++++ 2 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 packages/component/src/table/Table.ts diff --git a/packages/component/src/table/Table.stories.js b/packages/component/src/table/Table.stories.js index 79bc92e..ddef554 100644 --- a/packages/component/src/table/Table.stories.js +++ b/packages/component/src/table/Table.stories.js @@ -1,14 +1,97 @@ import { html } from 'lit-html'; import { TableCardComponent } from './TableCard'; +import { TableComponent, ColumnData } from './Table'; + +const columnData = [ + { + property: 'email', + label: 'email address', + index: 0, + align: 'left', + }, + { + property: 'postalCode', + label: 'postal code', + index: 5, + align: 'left', + }, + { + property: 'region', + label: 'state', + index: 4, + align: 'left', + }, + { + property: 'city', + label: 'city', + index: 3, + align: 'left', + }, + { + property: 'street', + label: 'street', + index: 2, + align: 'left', + }, + { + property: 'phoneNumber', + label: 'phone number', + index: 1, + align: 'left', + }, +]; + +const rowData = [ + { + email: 'joe@gmail.com', + phoneNumber: '(310) 555 5555', + street: '100 Camino Real', + city: 'Los Angeles', + region: 'CA', + postalCode: '90277', + }, + { + email: 'joe@gmail.com', + phoneNumber: '(310) 555 5555', + street: '100 Camino Real', + city: 'Los Angeles', + region: 'CA', + postalCode: '90277', + }, + { + email: 'joe@gmail.com', + phoneNumber: '(310) 555 5555', + street: '100 Camino Real', + city: 'Los Angeles', + region: 'CA', + postalCode: '90277', + }, + { + email: 'joe@gmail.com', + phoneNumber: '(310) 555 5555', + street: '100 Camino Real', + city: 'Los Angeles', + region: 'CA', + postalCode: '90277', + }, +]; + +const TableContext = { + rowData, + columnData, +}; export default { title: 'Components/Table', component: 'in-tablecard', }; -const Template = () => { - return html``; +const Template = ({ channelName, context }) => { + return html``; }; export const Primary = Template.bind({}); -Primary.args = {}; +Primary.args = { + channelName: 'table:one', + context: TableContext, +}; diff --git a/packages/component/src/table/Table.ts b/packages/component/src/table/Table.ts new file mode 100644 index 0000000..1a65ae4 --- /dev/null +++ b/packages/component/src/table/Table.ts @@ -0,0 +1,27 @@ +import { Component, attachTemplate, attachStyle, html, css } from '@in/common'; +export interface Column { + property: string; + label: string; + span?: number; + align: 'left' | 'center' | 'right' | 'justify'; + index: number; +} + +export type ColumnData = Column[]; + +@Component({ + selector: 'in-table', + custom: { extends: 'table' }, + style: css``, + template: html` + + + `, +}) +export class TableComponent extends HTMLTableElement { + constructor() { + super(); + attachTemplate(this); + attachStyle(this); + } +} From fd3d8cdc207b1c557f0f367406ef7cfb8be7c9bd Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sat, 18 Jan 2025 13:56:34 -0600 Subject: [PATCH 46/78] handiling CRUD events with broadcastchannel --- packages/component/src/card/Card.stories.js | 2 +- packages/component/src/card/Card.ts | 1 - packages/component/src/table/Table.stories.js | 9 ++ packages/component/src/table/Table.ts | 98 ++++++++++++++++++- packages/component/src/table/TableCard.ts | 25 ++++- 5 files changed, 131 insertions(+), 4 deletions(-) diff --git a/packages/component/src/card/Card.stories.js b/packages/component/src/card/Card.stories.js index 665dad1..f582017 100644 --- a/packages/component/src/card/Card.stories.js +++ b/packages/component/src/card/Card.stories.js @@ -1,7 +1,7 @@ import { CardComponent } from './Card'; const PrimaryTemplate = ({ image, headline, content, link }) => ` - +

${headline}

${content}

diff --git a/packages/component/src/card/Card.ts b/packages/component/src/card/Card.ts index a229177..d2d369c 100644 --- a/packages/component/src/card/Card.ts +++ b/packages/component/src/card/Card.ts @@ -8,7 +8,6 @@ import { Component, attachShadow, html, css } from '@in/common'; border-radius: var(--radius-md); box-shadow: var(--shadow); overflow: hidden; - max-width: 320px; } ::slotted(*) { padding-left: var(--padding-lg); diff --git a/packages/component/src/table/Table.stories.js b/packages/component/src/table/Table.stories.js index ddef554..db58a12 100644 --- a/packages/component/src/table/Table.stories.js +++ b/packages/component/src/table/Table.stories.js @@ -1,6 +1,7 @@ import { html } from 'lit-html'; import { TableCardComponent } from './TableCard'; import { TableComponent, ColumnData } from './Table'; +import { CardComponent } from './../card/Card'; const columnData = [ { @@ -87,6 +88,14 @@ export default { }; const Template = ({ channelName, context }) => { + const channel = new BroadcastChannel(channelName); + setTimeout(() => { + channel.postMessage({ + type: 'data', + detail: context, + }); + }, 0); + return html``; }; diff --git a/packages/component/src/table/Table.ts b/packages/component/src/table/Table.ts index 1a65ae4..44a3744 100644 --- a/packages/component/src/table/Table.ts +++ b/packages/component/src/table/Table.ts @@ -12,16 +12,112 @@ export type ColumnData = Column[]; @Component({ selector: 'in-table', custom: { extends: 'table' }, - style: css``, + style: css` + [is='in-table'] { + font-family: var(--font-default); + font-size: var(--font-body-md); + font-weight: var(--font-weight-default); + color: var(--color-neutral-500); + width: 100%; + } + [is='in-table'] th { + display: table-cell; + box-sizing: border-box; + margin-top: var(--margin-xs); + padding-left: calc(var(--padding-xxs) + var(--padding-sm)); + padding-right: var(--padding-xxs); + height: 44px; + vertical-align: middle; + font-weight: var(--font-weight-default); + } + [is='in-table'] tr { + height: 58px; + vertical-align: middle; + } + [is='in-table'] td { + padding-left: var(--padding-xxs); + padding-right: var(--padding-xxs); + } + `, template: html` `, }) export class TableComponent extends HTMLTableElement { + private channel: BroadcastChannel; + private columnData: ColumnData; constructor() { super(); attachTemplate(this); attachStyle(this); } + + static get observedAttributes() { + return ['channel']; + } + + attributeChangedCallback(name, prev, next) { + switch (name) { + case 'channel': + this.channel = new BroadcastChannel(next); + this.channel.onmessage = this.onMessage.bind(this); + break; + } + } + + onMessage(ev) { + switch (ev.data.type) { + case 'data': + this.onTableData(ev.data.detail); + break; + } + } + + onTableData(next) { + this.renderHeader(next.columnData); + this.renderRows(next.rowData); + } + + renderHeader(cols: ColumnData) { + this.columnData = cols.sort((a, b) => a.index - b.index); + const tr = document.createElement('tr'); + cols.forEach((colData) => { + const th = document.createElement('th'); + th.innerText = colData.label; + if (colData.span) { + th.colSpan = colData.span; + } + if (colData.align) { + th.align = colData.align; + } + tr.appendChild(th); + }); + this.$head.innerHTML = ''; + this.$head.appendChild(tr); + } + + renderRows(rows: any[]) { + this.$body.innerHTML = ''; + rows.forEach((rowData) => { + const tr = document.createElement('tr'); + this.columnData.forEach((colData) => { + const td = document.createElement('td'); + if (colData.align) { + td.align = colData.align; + } + td.innerText = rowData[colData.property]; + tr.appendChild(td); + }); + this.$body.append(tr); + }); + } + + get $head() { + return this.querySelector('thead'); + } + + get $body() { + return this.querySelector('tbody'); + } } diff --git a/packages/component/src/table/TableCard.ts b/packages/component/src/table/TableCard.ts index 6e532c4..2caf760 100644 --- a/packages/component/src/table/TableCard.ts +++ b/packages/component/src/table/TableCard.ts @@ -3,11 +3,34 @@ import { Component, attachShadow, html, css } from '@in/common'; @Component({ selector: 'in-tablecard', style: css``, - template: html``, + template: html` + +
+ +
+ `, }) export class TableCardComponent extends HTMLElement { + private channel: BroadcastChannel; constructor() { super(); attachShadow(this); } + + static get observedAttributes() { + return ['channel']; + } + + attributeChangedCallback(name, prev, next) { + switch (name) { + case 'channel': + this.channel = new BroadcastChannel(next); + this.$table.setAttribute('channel', next); + break; + } + } + + get $table(): HTMLTableElement { + return this.shadowRoot.querySelector('table'); + } } From a9e5d91a6deb80ace360f242be42d7b9e8f953eb Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sat, 18 Jan 2025 14:11:19 -0600 Subject: [PATCH 47/78] making the table editable --- packages/component/src/table/Table.ts | 13 ++++++ packages/component/src/table/TableCard.ts | 53 ++++++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/packages/component/src/table/Table.ts b/packages/component/src/table/Table.ts index 44a3744..1eac7dd 100644 --- a/packages/component/src/table/Table.ts +++ b/packages/component/src/table/Table.ts @@ -71,9 +71,22 @@ export class TableComponent extends HTMLTableElement { case 'data': this.onTableData(ev.data.detail); break; + case 'edit': + this.onEdit(); + break; + case 'readOnly': + this.onReadOnly(); + break; + case 'save': + this.onSave(); + break; } } + onEdit() {} + onReadOnly() {} + onSave() {} + onTableData(next) { this.renderHeader(next.columnData); this.renderRows(next.rowData); diff --git a/packages/component/src/table/TableCard.ts b/packages/component/src/table/TableCard.ts index 2caf760..e0940c4 100644 --- a/packages/component/src/table/TableCard.ts +++ b/packages/component/src/table/TableCard.ts @@ -1,4 +1,4 @@ -import { Component, attachShadow, html, css } from '@in/common'; +import { Component, attachShadow, html, css, Listen } from '@in/common'; @Component({ selector: 'in-tablecard', @@ -6,7 +6,17 @@ import { Component, attachShadow, html, css } from '@in/common'; template: html`
- +
`, }) @@ -30,7 +40,46 @@ export class TableCardComponent extends HTMLElement { } } + @Listen('click', '.button-edit') + editMode() { + this.$editButton.setAttribute('hidden', 'true'); + this.$saveButton.removeAttribute('hidden'); + this.$cancelButton.removeAttribute('hidden'); + this.channel.postMessage({ + type: 'edit', + }); + } + + @Listen('click', '.button-cancel') + readOnlyMode() { + this.$editButton.removeAttribute('hidden'); + this.$saveButton.setAttribute('hidden', 'true'); + this.$cancelButton.setAttribute('hidden', 'true'); + this.channel.postMessage({ + type: 'readOnly', + }); + } + + @Listen('click', '.button-save') + save() { + this.channel.postMessage({ + type: 'save', + }); + } + get $table(): HTMLTableElement { return this.shadowRoot.querySelector('table'); } + + get $editButton(): HTMLElement { + return this.shadowRoot.querySelector('.button-edit'); + } + + get $saveButton(): HTMLElement { + return this.shadowRoot.querySelector('.button-save'); + } + + get $cancelButton(): HTMLElement { + return this.shadowRoot.querySelector('.button-cancel'); + } } From 97e0deec948de732892a1d83c599a7e13233dbae Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Sat, 18 Jan 2025 17:15:42 -0600 Subject: [PATCH 48/78] using customevent to transmit row data --- packages/component/src/table/Table.stories.js | 2 + packages/component/src/table/Table.ts | 6 +- packages/component/src/table/Td.ts | 71 +++++++++++++++++++ packages/component/src/table/Tr.ts | 11 +++ 4 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 packages/component/src/table/Td.ts create mode 100644 packages/component/src/table/Tr.ts diff --git a/packages/component/src/table/Table.stories.js b/packages/component/src/table/Table.stories.js index db58a12..89dec41 100644 --- a/packages/component/src/table/Table.stories.js +++ b/packages/component/src/table/Table.stories.js @@ -2,6 +2,8 @@ import { html } from 'lit-html'; import { TableCardComponent } from './TableCard'; import { TableComponent, ColumnData } from './Table'; import { CardComponent } from './../card/Card'; +import { TrComponent } from './Tr'; +import { TextInputComponent } from '../input/TextInput'; const columnData = [ { diff --git a/packages/component/src/table/Table.ts b/packages/component/src/table/Table.ts index 1eac7dd..a8662f2 100644 --- a/packages/component/src/table/Table.ts +++ b/packages/component/src/table/Table.ts @@ -113,12 +113,14 @@ export class TableComponent extends HTMLTableElement { renderRows(rows: any[]) { this.$body.innerHTML = ''; rows.forEach((rowData) => { - const tr = document.createElement('tr'); + const tr = document.createElement('tr', { is: 'in-tr' }); this.columnData.forEach((colData) => { - const td = document.createElement('td'); + const td = document.createElement('td', { is: 'in-td' }); if (colData.align) { td.align = colData.align; } + td.setAttribute('value', rowData[colData.property]); + td.setAttribute('readonly', 'true'); td.innerText = rowData[colData.property]; tr.appendChild(td); }); diff --git a/packages/component/src/table/Td.ts b/packages/component/src/table/Td.ts new file mode 100644 index 0000000..df71517 --- /dev/null +++ b/packages/component/src/table/Td.ts @@ -0,0 +1,71 @@ +import { Component, attachTemplate, attachStyle, html, css } from '@in/common'; + +@Component({ + selector: 'in-td', + custom: { extends: 'td' }, + style: css` + .td-readonly { + display: table-cell; + box-sizing: border-box; + margin-top: var(--margin-xs); + padding-left: var(--padding-sm); + height: 44px; + vertical-align: middle; + } + .td-readonly[hidden='true'] { + display: none; + } + `, + template: html` + + + + + `, +}) +export class TdComponent extends HTMLTableCellElement { + constructor() { + super(); + attachTemplate(this); + attachStyle(this); + } + + static get observedAttributes() { + return ['value', 'readonly']; + } + + attributeChangedCallback(name, prev, next) { + switch (name) { + case 'value': + this.setValue(next); + break; + case 'readonly': + this.setMode(next === 'true'); + break; + } + } + + setMode(readOnly: boolean) { + if (readOnly) { + this.$readOnly.removeAttribute('hidden'); + this.$inputContainer.setAttribute('hidden', 'true'); + } else { + this.$readOnly.setAttribute('hidden', 'true'); + this.$inputContainer.removeAttribute('hidden'); + } + } + setValue(value: string) { + this.$readOnly.innerText = value; + } + + get $readOnly(): HTMLSpanElement { + return this.querySelector('.td-readonly'); + } + get $input(): HTMLInputElement { + return this.querySelector('in-textinput'); + } + + get $inputContainer(): HTMLSpanElement { + return this.querySelector('td-input'); + } +} diff --git a/packages/component/src/table/Tr.ts b/packages/component/src/table/Tr.ts new file mode 100644 index 0000000..291c385 --- /dev/null +++ b/packages/component/src/table/Tr.ts @@ -0,0 +1,11 @@ +import { Component } from '@in/common'; + +@Component({ + selector: 'in-tr', + custom: { extends: 'tr' }, +}) +export class TrComponent extends HTMLTableRowElement { + constructor() { + super(); + } +} From d52d370d8e707b9fd7e9faeebbd04953a39e9e43 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Mon, 20 Jan 2025 14:59:58 -0600 Subject: [PATCH 49/78] save method next --- packages/component/src/table/Table.ts | 80 ++++++++++++++++++++++++++- packages/component/src/table/Tr.ts | 13 ++++- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/packages/component/src/table/Table.ts b/packages/component/src/table/Table.ts index a8662f2..b65b74d 100644 --- a/packages/component/src/table/Table.ts +++ b/packages/component/src/table/Table.ts @@ -1,4 +1,6 @@ import { Component, attachTemplate, attachStyle, html, css } from '@in/common'; +import { TrComponent } from './Tr'; +import { TdComponent } from './Td'; export interface Column { property: string; label: string; @@ -47,6 +49,8 @@ export type ColumnData = Column[]; export class TableComponent extends HTMLTableElement { private channel: BroadcastChannel; private columnData: ColumnData; + private savedState: any[]; + private editIndex: number = 0; constructor() { super(); attachTemplate(this); @@ -83,8 +87,25 @@ export class TableComponent extends HTMLTableElement { } } - onEdit() {} - onReadOnly() {} + onEdit() { + const cells = this.querySelectorAll('td'); + if (!this.savedState) { + this.savedState = JSON.parse(JSON.stringify(this.state)); + } + cells.forEach(this.handleCellListeners.bind(this)); + this.onNext(); + } + onReadOnly() { + const cells = this.querySelectorAll('td'); + cells.forEach((td) => { + td.setAttribute('readonly', 'true'); + }); + if (this.savedState) { + this.renderRows(this.savedState); + this.savedState = undefined; + } + this.editIndex = 0; + } onSave() {} onTableData(next) { @@ -92,6 +113,24 @@ export class TableComponent extends HTMLTableElement { this.renderRows(next.rowData); } + get state() { + return Array.from(this.querySelector('tbody').querySelectorAll('tr')).map( + (tr: TrComponent) => tr.$rowData + ); + } + + onNext() { + const cells = this.querySelectorAll('td'); + if (!cells[this.editIndex]) { + return; + } + const input = cells[this.editIndex].querySelector( + 'in-textinput' + ) as HTMLInputElement; + if (input) { + input.focus(); + } + } renderHeader(cols: ColumnData) { this.columnData = cols.sort((a, b) => a.index - b.index); const tr = document.createElement('tr'); @@ -121,13 +160,50 @@ export class TableComponent extends HTMLTableElement { } td.setAttribute('value', rowData[colData.property]); td.setAttribute('readonly', 'true'); + td.setAttribute('data-property', colData.property); td.innerText = rowData[colData.property]; tr.appendChild(td); }); this.$body.append(tr); + tr.dispatchEvent( + new CustomEvent('data', { + detail: rowData, + }) + ); }); } + handleCellListeners(td: TdComponent, index: number) { + const tr = td.parentNode as TrComponent; + const input = td.querySelector('in-textinput') as HTMLInputElement; + if (input) { + input.value = td.getAttribute('value'); + td.setAttribute('readonly', 'false'); + input.onclick = (ev) => { + const cells = this.querySelectorAll('td'); + this.editIndex = Array.from(cells).indexOf(td); + }; + input.onkeyup = (ev) => { + td.setAttribute('value', input.value); + tr.dispatchEvent( + new CustomEvent('patch', { + detail: { + property: td.getAttribute('data-property'), + changes: td.getAttribute('value'), + }, + }) + ); + }; + input.onkeydown = (ev) => { + ev.stopPropagation(); + if (ev.key === 'Tab') { + this.editIndex = index; + this.onNext(); + } + }; + } + } + get $head() { return this.querySelector('thead'); } diff --git a/packages/component/src/table/Tr.ts b/packages/component/src/table/Tr.ts index 291c385..fe7df44 100644 --- a/packages/component/src/table/Tr.ts +++ b/packages/component/src/table/Tr.ts @@ -1,11 +1,22 @@ -import { Component } from '@in/common'; +import { Component, Listen } from '@in/common'; @Component({ selector: 'in-tr', custom: { extends: 'tr' }, }) export class TrComponent extends HTMLTableRowElement { + public $rowData: any; constructor() { super(); } + + @Listen('data') + setValue(ev: CustomEvent) { + this.$rowData = ev.detail; + } + + @Listen('patch') + patchData(ev: CustomEvent) { + this.$rowData[ev.detail.property] = ev.detail.changes; + } } From e42dd0b9084b3ac0ab3883a0df47ff49b8042819 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Tue, 21 Jan 2025 01:02:38 -0600 Subject: [PATCH 50/78] styling issues fixed --- packages/component/src/table/Table.ts | 37 ++++++++++++++++++++++- packages/component/src/table/TableCard.ts | 18 ++++++++++- packages/component/src/table/Td.ts | 5 ++- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/packages/component/src/table/Table.ts b/packages/component/src/table/Table.ts index b65b74d..05df677 100644 --- a/packages/component/src/table/Table.ts +++ b/packages/component/src/table/Table.ts @@ -40,6 +40,22 @@ export type ColumnData = Column[]; padding-left: var(--padding-xxs); padding-right: var(--padding-xxs); } + [is='in-table'] td.delete-cell button { + transform: translateY(-2px); + } + [is='in-table'] td.delete-cell[readonly='true'] { + display: none; + } + [is='in-table'] td:first-child { + padding-left: var(--padding-lg); + } + [is='in-table'] th:first-child { + padding-left: calc(var(--padding-lg) + var(--padding-sm)); + } + [is='in-table'] th:last-child, + [is='in-table'] td:last-child { + padding-right: var(--padding-lg); + } `, template: html` @@ -106,7 +122,26 @@ export class TableComponent extends HTMLTableElement { } this.editIndex = 0; } - onSave() {} + onSave() { + const data: TrComponent[] = this.state; + + if (this.querySelectorAll('td')[this.editIndex]) { + this.querySelectorAll('td')[this.editIndex].setAttribute( + 'readonly', + 'true' + ); + } + + this.savedState = undefined; + this.editIndex = 0; + + this.channel.postMessage({ + type: 'change', + detail: data, + }); + + this.renderRows(data); + } onTableData(next) { this.renderHeader(next.columnData); diff --git a/packages/component/src/table/TableCard.ts b/packages/component/src/table/TableCard.ts index e0940c4..1380e3b 100644 --- a/packages/component/src/table/TableCard.ts +++ b/packages/component/src/table/TableCard.ts @@ -2,7 +2,23 @@ import { Component, attachShadow, html, css, Listen } from '@in/common'; @Component({ selector: 'in-tablecard', - style: css``, + style: css` + :host .primary[is='in-button'], + :host .secondary[is='in-button'] { + min-width: 160px; + margin-left: var(--margin-lg); + } + + .table-footer { + display: flex; + justify-content: space-between; + padding-top: var(--padding-md); + } + + [hidden] { + display: none; + } + `, template: html`
diff --git a/packages/component/src/table/Td.ts b/packages/component/src/table/Td.ts index df71517..756cb85 100644 --- a/packages/component/src/table/Td.ts +++ b/packages/component/src/table/Td.ts @@ -27,13 +27,16 @@ export class TdComponent extends HTMLTableCellElement { constructor() { super(); attachTemplate(this); - attachStyle(this); } static get observedAttributes() { return ['value', 'readonly']; } + connectedCallback() { + attachStyle(this); + } + attributeChangedCallback(name, prev, next) { switch (name) { case 'value': From 99dcadd8d1b89d6d130efa8b9d8fdaf0120a4503 Mon Sep 17 00:00:00 2001 From: Kelsey Jackson Date: Tue, 21 Jan 2025 01:40:32 -0600 Subject: [PATCH 51/78] this this chapter is bogus --- packages/common/src/event/listen.ts | 5 +++ packages/component/src/table/Table.ts | 42 +++++++++++++++++++++++ packages/component/src/table/TableCard.ts | 26 ++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/packages/common/src/event/listen.ts b/packages/common/src/event/listen.ts index 7800dd6..0f8bc77 100644 --- a/packages/common/src/event/listen.ts +++ b/packages/common/src/event/listen.ts @@ -16,23 +16,28 @@ export function Listen( const { connectedCallback = () => {}, disconnectedCallback = () => {} } = target; const symbolMethod = Symbol(key); + function getContext(context) { const root = context.shadowRoot ? context.shadowRoot : context; return selector ? root.querySelector(selector) : context; } + function addListener() { const handler = (this[symbolMethod] = (...args) => { descriptor.value.apply(this, args); }); getContext(this).addEventListener(eventName, handler); } + function removeListener() { getContext(this).removeEventListener(eventName, this[symbolMethod]); } + target.connectedCallback = function connectedCallbackWrapper() { connectedCallback.call(this); addListener.call(this); }; + target.disconnectedCallback = function disconnectedCallbackWrapper() { disconnectedCallback.call(this); removeListener.call(this); diff --git a/packages/component/src/table/Table.ts b/packages/component/src/table/Table.ts index 05df677..c87bfdf 100644 --- a/packages/component/src/table/Table.ts +++ b/packages/component/src/table/Table.ts @@ -67,6 +67,7 @@ export class TableComponent extends HTMLTableElement { private columnData: ColumnData; private savedState: any[]; private editIndex: number = 0; + private blankRowData: any; constructor() { super(); attachTemplate(this); @@ -88,6 +89,9 @@ export class TableComponent extends HTMLTableElement { onMessage(ev) { switch (ev.data.type) { + case 'add': + this.onAdd(); + break; case 'data': this.onTableData(ev.data.detail); break; @@ -103,6 +107,39 @@ export class TableComponent extends HTMLTableElement { } } + onAdd() { + if (!this.savedState) { + this.savedState = JSON.parse(JSON.stringify(this.state)); + } + + const rowData = this.blankRowData; + + const tr = document.createElement('tr', { is: 'in-tr' }); + this.columnData.forEach((colData) => { + const td = document.createElement('td', { is: 'in-td' }); + if (colData.align) { + td.align = colData.align; + } + td.setAttribute('data-property', colData.property); + td.setAttribute('readonly', 'false'); + td.setAttribute('value', rowData[colData.property]); + tr.appendChild(td); + }); + + this.$body.appendChild(tr); + tr.dispatchEvent( + new CustomEvent('data', { + detail: rowData, + }) + ); + const cells = this.querySelectorAll('td'); + cells.forEach(this.handleCellListeners.bind(this)); + this.editIndex = Array.from(cells).indexOf( + tr.children[0] as HTMLTableCellElement + ); + this.onNext(); + } + onEdit() { const cells = this.querySelectorAll('td'); if (!this.savedState) { @@ -205,6 +242,11 @@ export class TableComponent extends HTMLTableElement { detail: rowData, }) ); + + this.blankRowData = {}; + this.columnData.forEach((colData) => { + this.blankRowData[colData.property] = ''; + }); }); } diff --git a/packages/component/src/table/TableCard.ts b/packages/component/src/table/TableCard.ts index 1380e3b..6c6df50 100644 --- a/packages/component/src/table/TableCard.ts +++ b/packages/component/src/table/TableCard.ts @@ -23,6 +23,17 @@ import { Component, attachShadow, html, css, Listen } from '@in/common';