initial commit

Signed-off-by: Mitch Hijlkema <mitch@hijlkema.codes>
This commit is contained in:
2023-08-24 14:04:43 +02:00
parent 844188ee58
commit a6d98a9d84
42 changed files with 8124 additions and 20 deletions

View File

@@ -0,0 +1,25 @@
{
"extends": ["../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.json"],
"parser": "jsonc-eslint-parser",
"rules": {
"@nx/dependency-checks": "error"
}
}
]
}

View File

@@ -0,0 +1,11 @@
# \_internal-styles
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build _internal-styles` to build the library.
## Running unit tests
Run `nx test _internal-styles` to execute the unit tests via [Jest](https://jestjs.io).

View File

@@ -0,0 +1,11 @@
/* eslint-disable */
export default {
displayName: '_internal-styles',
preset: '../../../jest.preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../../coverage/libs/_internal/styles',
};

View File

@@ -0,0 +1,10 @@
{
"name": "z-styles",
"version": "0.0.1",
"dependencies": {
"tslib": "^2.3.0"
},
"type": "commonjs",
"main": "./src/index.js",
"typings": "./src/index.d.ts"
}

View File

@@ -0,0 +1,43 @@
{
"name": "_internal-styles",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/_internal/styles/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/_internal/styles",
"main": "libs/_internal/styles/src/index.ts",
"tsConfig": "libs/_internal/styles/tsconfig.lib.json",
"assets": ["libs/_internal/styles/*.md"]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": [
"libs/_internal/styles/**/*.ts",
"libs/_internal/styles/package.json"
]
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/_internal/styles/jest.config.ts",
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
}
},
"tags": []
}

View File

@@ -0,0 +1,3 @@
export * from './lib/normalize';
export * from './lib/variable.helper';

View File

@@ -0,0 +1,72 @@
import { css } from 'lit';
export const normalize = css`
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
ol,
ul {
list-style: none;
margin: 0;
padding: 0;
}
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
vertical-align: middle;
}
img,
video {
max-width: 100%;
height: auto;
}
*,
::before,
::after {
border-width: 0;
border-style: solid;
border-color: currentColor;
}
i,
svg {
width: 1em;
height: 1em;
}
:host {
display: block;
}
`;

View File

@@ -0,0 +1,64 @@
import { CSSResult, css, unsafeCSS } from 'lit';
export class VariableHelper {
private property: string | undefined;
private variableName: string | undefined;
private groupModifier: string | undefined;
private defaultValue: string | CSSResult = '/*! */';
private isPrivate = false;
public asPrivate(isPrivate = true) {
this.isPrivate = isPrivate;
return this;
}
public withDefaultValue(value: string | CSSResult) {
this.defaultValue = value;
return this;
}
public withProperty(property: string) {
this.property = property;
return this;
}
public withVariableName(name: string) {
this.variableName = name;
return this;
}
public withGroupModifier(modifier: string, ...modifiers: string[]) {
this.groupModifier = [modifier, ...modifiers].join('--');
return this;
}
toCss() {
if (!this.property) {
return css`
${unsafeCSS(this.buildVariableName())}
`;
}
return css`
${unsafeCSS(this.property)}: ${unsafeCSS(this.buildVariableName())};
`;
}
private buildVariableName() {
const variableName = [];
if (this.groupModifier) {
variableName.push(this.groupModifier);
}
if (this.variableName) {
variableName.push(this.variableName);
}
return `var(--${this.isPrivate ? '_' : ''}${variableName.join('--')}, ${
this.defaultValue
})`;
}
}

View File

@@ -0,0 +1,22 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"],
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
}

View File

@@ -0,0 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}

10
libs/accordion/.babelrc Normal file
View File

@@ -0,0 +1,10 @@
{
"presets": [
[
"@nx/js/babel",
{
"useBuiltIns": "usage"
}
]
]
}

View File

@@ -0,0 +1,25 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.json"],
"parser": "jsonc-eslint-parser",
"rules": {
"@nx/dependency-checks": "error"
}
}
]
}

11
libs/accordion/README.md Normal file
View File

@@ -0,0 +1,11 @@
# accordion
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build accordion` to build the library.
## Running unit tests
Run `nx test accordion` to execute the unit tests via [Jest](https://jestjs.io).

73
libs/accordion/index.html Normal file
View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Lit + TS</title>
<!-- the props -->
<link rel="stylesheet" href="https://unpkg.com/open-props" />
<!-- optional imports that use the props -->
<link
rel="stylesheet"
href="https://unpkg.com/open-props/normalize.min.css"
/>
<script type="module" src="/src/lib/accordion.component.ts"></script>
<script type="module" src="/src/lib/accordion-group.component.ts"></script>
</head>
<body>
<z-accordion
accordion-title="This is lorem ipsum."
icon-type="plus-to-cross"
>
Mollit eu excepteur ex ea magna id nostrud duis aliqua cillum aute. Minim
cupidatat cillum aute esse ea culpa proident enim consectetur in ullamco
mollit labore id. Ipsum adipisicing esse ex irure ut nostrud adipisicing
velit nulla ullamco dolor consequat. Occaecat sint veniam quis aliquip.
Aliquip elit commodo labore sit non nostrud dolore aute officia sint
cillum ullamco veniam dolore. Et tempor aliquip elit amet adipisicing
esse.
</z-accordion>
<hr />
<z-accordion>
<h3 slot="header">This is lorem ipsum from a slot.</h3>
Mollit eu excepteur ex ea magna id nostrud duis aliqua cillum aute. Minim
cupidatat cillum aute esse ea culpa proident enim consectetur in ullamco
mollit labore id. Ipsum adipisicing esse ex irure ut nostrud adipisicing
velit nulla ullamco dolor consequat. Occaecat sint veniam quis aliquip.
Aliquip elit commodo labore sit non nostrud dolore aute officia sint
cillum ullamco veniam dolore. Et tempor aliquip elit amet adipisicing
esse.
</z-accordion>
<hr />
<z-accordion.group>
<z-accordion
accordion-title="This is lorem ipsum."
icon-type="plus-to-cross"
>
Mollit eu excepteur ex ea magna id nostrud duis aliqua cillum aute.
Minim cupidatat cillum aute esse ea culpa proident enim consectetur in
ullamco mollit labore id. Ipsum adipisicing esse ex irure ut nostrud
adipisicing velit nulla ullamco dolor consequat. Occaecat sint veniam
quis aliquip. Aliquip elit commodo labore sit non nostrud dolore aute
officia sint cillum ullamco veniam dolore. Et tempor aliquip elit amet
adipisicing esse.
</z-accordion>
<hr />
<z-accordion>
<h3 slot="header">This is lorem ipsum from a slot.</h3>
Mollit eu excepteur ex ea magna id nostrud duis aliqua cillum aute.
Minim cupidatat cillum aute esse ea culpa proident enim consectetur in
ullamco mollit labore id. Ipsum adipisicing esse ex irure ut nostrud
adipisicing velit nulla ullamco dolor consequat. Occaecat sint veniam
quis aliquip. Aliquip elit commodo labore sit non nostrud dolore aute
officia sint cillum ullamco veniam dolore. Et tempor aliquip elit amet
adipisicing esse.
</z-accordion>
</z-accordion.group>
</body>
</html>

View File

@@ -0,0 +1,11 @@
/* eslint-disable */
export default {
displayName: 'accordion',
preset: '../../jest.preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/libs/accordion',
};

View File

@@ -0,0 +1,8 @@
{
"name": "@hijlkema-codes/z-accordion",
"version": "0.0.1",
"dependencies": {},
"main": "./index.js",
"module": "./index.mjs",
"typings": "./index.d.ts"
}

View File

@@ -0,0 +1,44 @@
{
"name": "accordion",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/accordion/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/vite:build",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/accordion"
}
},
"publish": {
"command": "node tools/scripts/publish.mjs accordion {args.ver} {args.tag}",
"dependsOn": ["build"]
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": [
"libs/accordion/**/*.ts",
"libs/accordion/package.json"
]
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accordion/jest.config.ts",
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
}
},
"tags": ["type:component", ""]
}

View File

@@ -0,0 +1 @@
export * from './lib/accordion.component';

View File

@@ -0,0 +1,33 @@
import { LitElement, TemplateResult, html } from 'lit';
import { customElement, queryAssignedElements } from 'lit/decorators.js';
import AccordionComponent from './accordion.component';
@customElement('z-accordion.group')
export default class AccordionGroupComponent extends LitElement {
@queryAssignedElements({ selector: 'z-accordion' })
public items!: NodeListOf<AccordionComponent>;
protected override firstUpdated() {
this.items.forEach((item) => {
item.addEventListener('open', () => {
this.items.forEach((i) => {
if (i !== item) {
i.open = false;
}
});
});
item.addEventListener('close', () => {
this.items.forEach((i) => {
if (i !== item) {
i.open = false;
}
});
});
});
}
protected override render(): TemplateResult<1> {
return html`<slot></slot>`;
}
}

View File

@@ -0,0 +1,81 @@
import { normalize } from '@hijlkema-codes/internal/z-styles';
import { LitElement, TemplateResult, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import {
bodyStyles,
chevronStyles,
headerStyles,
hostVariables,
plusToCrossStyles,
plustoMinusStyles,
} from './styles';
export const enum Icon {
chevronDown = 'chevron-down',
plusMinus = 'plus-to-minus',
plusCross = 'plus-to-cross',
chevronSide = 'chevron-side',
}
@customElement('z-accordion')
export default class AccordionComponent extends LitElement {
static override get styles() {
return [
normalize,
hostVariables,
headerStyles,
bodyStyles,
chevronStyles,
plustoMinusStyles,
plusToCrossStyles,
];
}
@property({ attribute: 'accordion-title' })
public accordionTitle: string | undefined;
@property({ reflect: true, type: Boolean })
public open = false;
@property({ attribute: 'icon-type' })
public iconType: Icon = Icon.chevronDown;
protected override render(): TemplateResult<1> {
return html`
<section>
${this.renderTitle()}
<div><slot></slot></div>
</section>
`;
}
protected renderTitle(): TemplateResult<1> {
let titleElement = html`<slot name="header"></slot>`;
if (this.accordionTitle) {
titleElement = html`<h3>${this.accordionTitle}</h3>`;
}
return html` <header @click=${this.toggleOpen}>
${titleElement} ${this.renderChevron()}
</header>`;
}
protected renderChevron(): TemplateResult<1> {
switch (this.iconType) {
case Icon.plusCross:
return html`<span class="o-icon__plus-to-cross"></span>`;
case Icon.plusMinus:
return html`<span class="o-icon__plus-to-minus"></span>`;
case Icon.chevronDown:
default:
return html`<span class="o-icon__chevron-down"></span>`;
}
}
private toggleOpen(): void {
this.open = !this.open;
this.dispatchEvent(new Event(this.open ? 'open' : 'close'));
}
}

View File

@@ -0,0 +1,13 @@
import { css } from 'lit';
export const bodyStyles = css`
div {
padding-inline: var(--_body--padding-inline);
padding-block: var(--_body--padding-block);
display: none;
}
:host([open]) div {
display: block;
}
`;

View File

@@ -0,0 +1,142 @@
import { VariableHelper } from '@hijlkema-codes/internal/z-styles';
import { css } from 'lit';
const iconColor = new VariableHelper()
.withGroupModifier('accordion', 'icon')
.withVariableName('color')
.withDefaultValue('currentColor')
.toCss();
export const headerStyles = css`
header {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
padding-inline: var(--_padding-inline);
border-width: var(--_header--border-width);
border-style: solid;
border-color: var(--_header--border-color);
}
`;
export const chevronStyles = css`
.o-icon__chevron-down {
width: 1rem;
height: 1rem;
display: block;
position: relative;
}
.o-icon__chevron-down::before,
.o-icon__chevron-down::after {
content: '';
background-color: ${iconColor};
position: absolute;
top: 50%;
height: 1px;
width: 50%;
border: 1px solid ${iconColor};
transition: transform 0.3s ease-out;
}
.o-icon__chevron-down::before {
transform: translateY(-50%)
rotate(calc(var(--_rotation-displacement, 1) * 45deg));
left: 0;
}
.o-icon__chevron-down::after {
transform: translateY(-50%)
rotate(calc(var(--_rotation-displacement, 1) * -45deg));
right: 0;
}
:host([open]) .o-icon__chevron-down {
--_rotation-displacement: -1;
}
:host([open]) .o-icon__chevron-down::before,
:host([open]) .o-icon__chevron-down::after {
transition-timing-function: ease-in;
}
`;
export const plustoMinusStyles = css`
.o-icon__plus-to-minus {
width: 1rem;
height: 1rem;
display: block;
position: relative;
}
.o-icon__plus-to-minus::before,
.o-icon__plus-to-minus::after {
content: '';
background-color: ${iconColor};
position: absolute;
top: 50%;
height: 1px;
width: 100%;
border: 1px solid ${iconColor};
transition: transform 0.3s ease-out;
}
.o-icon__plus-to-minus::before {
transform: translateY(-50%)
rotate(calc(var(--_rotation-displacement, 1) * 90deg));
}
.o-icon__plus-to-minus::after {
transform: translateY(-50%);
}
:host([open]) .o-icon__plus-to-minus {
--_rotation-displacement: 2;
}
:host([open]) .o-icon__plus-to-minus::before,
:host([open]) .o-icon__plus-to-minus::after {
transition-timing-function: ease-in;
}
`;
export const plusToCrossStyles = css`
.o-icon__plus-to-cross {
width: 1rem;
height: 1rem;
display: block;
position: relative;
}
.o-icon__plus-to-cross::before,
.o-icon__plus-to-cross::after {
content: '';
background-color: ${iconColor};
position: absolute;
top: 50%;
height: 1px;
width: 100%;
border: 1px solid ${iconColor};
transition: transform 0.3s ease-out;
}
.o-icon__plus-to-cross::before {
transform: translateY(-50%)
rotate(calc(var(--_rotation-displacement, 2) * 135deg));
}
.o-icon__plus-to-cross::after {
transform: translateY(-50%)
rotate(calc(var(--_rotation-displacement, 0) * 45deg));
}
:host([open]) .o-icon__plus-to-cross {
--_rotation-displacement: 1;
}
:host([open]) .o-icon__plus-to-cross::before,
:host([open]) .o-icon__plus-to-cross::after {
transition-timing-function: ease-in;
}
`;

View File

@@ -0,0 +1,3 @@
export * from './body.styles';
export * from './header.styles';
export * from './variables.styles';

View File

@@ -0,0 +1,45 @@
import { VariableHelper } from '@hijlkema-codes/internal/z-styles';
import { css } from 'lit';
export const hostVariables = css`
:host {
${new VariableHelper()
.withProperty('--_padding-inline')
.withVariableName('padding-inline')
.withGroupModifier('accordion')
.withDefaultValue('1.25rem')
.toCss()}
${new VariableHelper()
.withProperty('--_header--border-width')
.withGroupModifier('accordion', 'header')
.withVariableName('border-width')
.withDefaultValue('0 0 1px 0')
.toCss()}
${new VariableHelper()
.withProperty('--_header--border-color')
.withGroupModifier('accordion', 'header')
.withVariableName('border-color')
.withDefaultValue('hsl(0, 0, 2%)')
.toCss()}
${new VariableHelper()
.withProperty('--_body--padding-block')
.withGroupModifier('accordion', 'body')
.withVariableName('padding-block')
.withDefaultValue('1rem')
.toCss()}
${new VariableHelper()
.withProperty('--_body--padding-inline')
.withGroupModifier('accordion', 'body')
.withVariableName('padding-inline')
.withDefaultValue(
new VariableHelper()
.asPrivate()
.withVariableName('padding-inline')
.toCss()
)
.toCss()}
}
`;

View File

@@ -0,0 +1,22 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"],
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
}

View File

@@ -0,0 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}

View File

@@ -0,0 +1,43 @@
/// <reference types="vitest" />
import { defineConfig } from 'vite';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig({
cacheDir: '../../node_modules/.vite/accordion',
plugins: [
dts({
entryRoot: 'src',
tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'),
skipDiagnostics: true,
}),
nxViteTsPaths(),
],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: 'accordion',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es', 'cjs'],
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: [],
},
},
});