29 Commits

Author SHA1 Message Date
fb5471c177 feat: clean up apps and add publish
All checks were successful
Release / build_test (pull_request) Successful in 51s
2025-11-30 20:15:41 +01:00
134dc79f3c Implement better pipeline (#3)
Reviewed-on: #3
2025-11-30 14:02:21 +01:00
3f4d611a18 Merge pull request 'feature/remove-fleet' (#2) from feature/remove-fleet into main
Reviewed-on: #2
2025-11-29 23:29:17 +01:00
5ddd6501b6 feat: add release workflow for pull requests
Some checks failed
Release / build_test (pull_request) Failing after 39s
2025-11-29 23:28:56 +01:00
268e0a767c remove onedev 2025-11-29 22:56:42 +01:00
44b51ca055 Edit .onedev-buildspec.yml 2025-11-28 20:54:43 +01:00
8863ffd1f7 feat: add initial build specification for publishing 2025-11-28 20:52:29 +01:00
0a179ec3dc Delete .onedev-buildspec.yml 2025-11-28 20:44:59 +01:00
16965d779f Edit .onedev-buildspec.yml 2025-11-28 20:39:47 +01:00
141c2a0a16 chore: update build job steps in build specification 2025-11-28 20:38:49 +01:00
9815ade65a fix: add build job to the build specification 2025-11-28 20:37:23 +01:00
ec7f0c2f4f Merge branch 'feature/remove-fleet' of https://onedev.hijlkema.codes/z-elements into feature/remove-fleet 2025-11-28 20:28:14 +01:00
301f32b39c chore: remove staging deployment script from build specification 2025-11-28 20:27:10 +01:00
249c00e90c Edit .onedev-buildspec.yml 2025-11-28 20:25:08 +01:00
21238c5d41 Edit .onedev-buildspec.yml 2025-11-28 20:24:58 +01:00
c709ce9e8d chore: add deployment script for staging environment 2025-11-28 20:23:25 +01:00
f3c8d121ae chore: add initial build specification file 2025-11-28 20:17:40 +01:00
ce0e1742d2 chore: update dependencies and devDependencies in package.json
- Updated lit to version 3.3.1
- Upgraded react and react-dom to version 19.2.0
- Updated tslib to version 2.8.1
- Upgraded zod to version 4.1.13
- Updated @babel/plugin-proposal-decorators to version 7.28.0
- Upgraded @playwright/test to version 1.57.0
- Updated @storybook/test-runner to version 0.24.2
- Updated @swc-node/register to version 1.11.1
- Updated @swc/core to version 1.15.3
- Updated @swc/helpers to version 0.5.17
- Upgraded @trivago/prettier-plugin-sort-imports to version 6.0.0
- Updated @types/node to version 24.10.1
- Upgraded @typescript-eslint/eslint-plugin and parser to version 8.48.0
- Updated @vitest/ui to version 4.0.14
- Upgraded eslint to version 9.39.1
- Updated eslint-config-prettier to version 10.1.8
- Upgraded eslint-plugin-playwright to version 2.3.0
- Updated jest and related packages to version 30.2.0
- Updated jiti to version 2.6.1
- Updated jsdom to version 27.2.0
- Updated prettier to version 3.7.1
- Updated rxjs to version 7.8.2
- Upgraded storybook to version 10.1.2
- Updated verdaccio to version 6.2.3
- Updated vite to version 7.2.4
- Updated vitest to version 4.0.14
2025-11-28 20:02:46 +01:00
62d24417d4 update dependencies 2025-11-28 19:49:30 +01:00
a9c4ae446d chore: remove fleet settings file 2025-11-28 10:11:40 +01:00
d614193974 Merge pull request #1 from Pridestalker/develop
Develop
2025-11-28 09:44:32 +01:00
e2bacc283d feat: add review 2024-08-12 17:44:58 +02:00
89e819ece1 feat: can build again 2024-08-02 16:07:07 +02:00
e89c62dde8 feat: updates 2024-08-02 14:03:47 +02:00
68be013f8f chore: maintenance 2024-08-02 13:57:10 +02:00
638e1eb739 Work on panels 2023-10-28 16:43:43 +02:00
ad59f07d2b Clean up internal type usages 2023-09-02 21:02:50 +02:00
41830bbca5 feat: side panels
Signed-off-by: Mitch Hijlkema <mitch@hijlkema.codes>
2023-08-31 17:03:27 +02:00
14c1b97622 Create Libraries and basic tooltip 2023-08-25 22:09:18 +02:00
123 changed files with 23666 additions and 8167 deletions

View File

@@ -24,12 +24,18 @@
{
"files": ["*.ts", "*.tsx"],
"extends": ["plugin:@nx/typescript"],
"rules": {}
"rules": {
"@typescript-eslint/no-extra-semi": "error",
"no-extra-semi": "off"
}
},
{
"files": ["*.js", "*.jsx"],
"extends": ["plugin:@nx/javascript"],
"rules": {}
"rules": {
"@typescript-eslint/no-extra-semi": "error",
"no-extra-semi": "off"
}
},
{
"files": ["*.spec.ts", "*.spec.tsx", "*.spec.js", "*.spec.jsx"],

View File

@@ -0,0 +1,134 @@
name: Publish
concurrency:
cancel-in-progress: false
group: publish-${{ github.ref_name }}
env:
ACT_OWNER: ${{ github.repository_owner }}
ACT_REPOSITORY: ${{ github.repository }}
CGO_ENABLED: 0
# Default comma-separated list of projects to build+publish. Can be overridden
# when manually dispatching the workflow via the `projects` input.
PUBLISH_PROJECTS: 'reviews-stars'
on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
projects:
description: 'Comma-separated list of Nx projects to build and publish'
required: false
default: 'reviews-stars'
version:
description: 'Semantic version to publish (e.g. 1.2.3). If omitted for tag runs, the tag name is used.'
required: false
npm_tag:
description: 'NPM dist-tag to use (overrides automatic selection). default: auto (latest for release, next for prerelease)'
required: false
jobs:
build:
runs-on: ubuntu-latest
outputs:
projects: ${{ steps.set-projects.outputs.projects }}
env:
PUBLISH_PROJECTS: ${{ github.event.inputs.projects || env.PUBLISH_PROJECTS }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: git fetch --force --tags
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 22
- name: Install dependencies
run: npm ci --legacy-peer-deps
- name: Build projects
run: |
echo "Projects to build: $PUBLISH_PROJECTS"
npx nx run-many --target=build --projects="$PUBLISH_PROJECTS"
- name: Upload dist artifact
uses: actions/upload-artifact@v4
with:
name: dist
path: dist
- name: Set projects output (JSON array)
id: set-projects
run: |
# Convert comma-separated list into JSON array
IFS=',' read -ra PROJS <<< "$PUBLISH_PROJECTS"
json='['
first=true
for p in "${PROJS[@]}"; do
p_trimmed=$(echo "$p" | xargs)
if [ "$first" = true ]; then
json+="\"$p_trimmed\""
first=false
else
json+=",\"$p_trimmed\""
fi
done
json+=']'
echo "projects=$json" >> "$GITHUB_OUTPUT"
publish:
runs-on: ubuntu-latest
needs: build
strategy:
fail-fast: false
matrix:
project: ${{ fromJson(needs.build.outputs.projects) }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download dist artifact
uses: actions/download-artifact@v4
with:
name: dist
path: ./
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 22
- name: Determine version and npm tag
id: set-version
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
if [ -n "${{ github.event.inputs.version }}" ]; then
VERSION="${{ github.event.inputs.version }}"
else
echo "No version provided for manual dispatch. Exiting." >&2
exit 1
fi
else
VERSION="${GITHUB_REF_NAME#v}"
fi
if [ -n "${{ github.event.inputs.npm_tag }}" ]; then
NPM_TAG="${{ github.event.inputs.npm_tag }}"
else
if echo "$VERSION" | grep -q "-"; then
NPM_TAG="next"
else
NPM_TAG="latest"
fi
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "npm_tag=$NPM_TAG" >> "$GITHUB_OUTPUT"
- name: Configure npm auth
run: |
echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > ~/.npmrc
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish project
run: |
echo "Publishing ${{ matrix.project }} with version ${VERSION} and tag ${NPM_TAG}"
node tools/scripts/publish.mjs "${{ matrix.project }}" "${VERSION}" "${NPM_TAG}"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -0,0 +1,37 @@
name: Release
concurrency:
cancel-in-progress: true
group: test-pr-${{ github.event.pull_request.number }}
env:
ACT_OWNER: ${{ github.repository_owner }}
ACT_REPOSITORY: ${{ github.repository }}
CGO_ENABLED: 0
on:
pull_request:
types:
- opened
- synchronize
- reopened
- edited
jobs:
build_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: git fetch --force --tags
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 22
- name: Install dependencies
run: npm ci --legacy-peer-deps
- name: Build libraries
run: npx nx run-many -t build --projects="reviews-stars"
- name: Run tests
run: npx nx run-many -t test --code-coverage --passWithNoTests --projects="reviews-stars"

8
.gitignore vendored
View File

@@ -16,6 +16,7 @@ node_modules
*.launch
.settings/
*.sublime-workspace
.fleet
# IDE - VSCode
.vscode/*
@@ -37,3 +38,10 @@ testem.log
# System Files
.DS_Store
Thumbs.db
.nx/cache
.nx/workspace-data
vite.config.*.timestamp*
.cursor/rules/nx-rules.mdc
.github/instructions/nx.instructions.md
act_runner*

View File

@@ -1,3 +1,5 @@
# Add files here to ignore them from prettier formatting
/dist
/coverage
/coverage
/.nx/cache
/.nx/workspace-data

View File

@@ -1,3 +1,9 @@
{
"singleQuote": true
"plugins": ["@trivago/prettier-plugin-sort-imports"],
"singleQuote": true,
"printWidth": 140,
"importOrder": ["^^@z-(.*)$", "^lit(.*)$", "rxjs", "^[./]"],
"importOrderSeparation": true,
"importOrderGroupNamespaceSpecifiers": true,
"importOrderParserPlugins": ["decorators", "typescript"]
}

View File

@@ -1,28 +0,0 @@
# path to a directory with all packages
storage: ../tmp/local-registry/storage
# a list of other known repositories we can talk to
uplinks:
npmjs:
url: https://verdaccio.hijlkema.codes/
maxage: 60m
packages:
'**':
# give all users (including non-authenticated users) full access
# because it is a local registry
access: $all
publish: $all
unpublish: $all
# if package is not available locally, proxy requests to npm registry
proxy: npmjs
# log settings
logs:
type: stdout
format: pretty
level: warn
publish:
allow_offline: true # set offline to true to allow publish offline

View File

@@ -0,0 +1,175 @@
# Instructions for LLM: Transform Storybook Config Files from CommonJS to ESM
## Task Overview
Find all .storybook/main.ts and .storybook/main.js files in the workspace and transform
any CommonJS (CJS) configurations to ES Modules (ESM).
### Step 1: Find All Storybook Config Files
Use glob patterns to locate all Storybook main configuration files:
**/.storybook/main.js
**/.storybook/main.ts
### Step 2: Identify CommonJS vs ESM
For each file found, read its contents and determine if it uses CommonJS syntax by
checking for:
CommonJS indicators:
- `module.exports =` or `module.exports.`
- `exports.`
- `require()` function calls
ESM indicators (already correct):
- export default
- export const/export function
- import statements
### Step 3: Transform CJS to ESM
For each file identified as CommonJS, perform the following transformations:
A. Convert `module.exports`
// FROM (CJS):
```
module.exports = {
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials']
};
```
// TO (ESM):
```
export default {
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials']
};
```
B. Convert `require()` to import
// FROM (CJS):
```
const { nxViteTsPaths } = require('@nx/vite/plugins/nx-tsconfig-paths.plugin');
const { mergeConfig } = require('vite');
```
// TO (ESM):
```
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { mergeConfig } from 'vite';
```
C. Handle `path.join()` patterns
// FROM (CJS):
```
const path = require('path');
const rootMain = require(path.join(__dirname, '../../.storybook/main'));
```
// TO (ESM):
```
import { join } from 'path';
import rootMain from '../../.storybook/main';
```
D. Handle Dynamic Requires in Config Functions
// FROM (CJS):
```
module.exports = {
viteFinal: async (config) => {
const { mergeConfig } = require('vite');
return mergeConfig(config, {});
}
};
```
// TO (ESM):
```
import { mergeConfig } from 'vite';
export default {
viteFinal: async (config) => {
return mergeConfig(config, {});
}
};
```
### Step 4: Validation Checks
After transformation, verify:
1. All require() calls have been converted to import statements at the top of the file
2. All module.exports have been converted to export default or named exports
3. Imports are at the top of the file (before the export)
4. The file maintains proper TypeScript typing if it's a .ts file
### Step 5: Report Results
Provide a summary of:
- Total files found
- Files that were already ESM (no changes needed)
- Files that were transformed from CJS to ESM
- List the specific files that were modified
### Example Complete Transformation
Before (CJS):
```
const path = require('path');
const { mergeConfig } = require('vite');
module.exports = {
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials'],
viteFinal: async (config) => {
return mergeConfig(config, {
resolve: {
alias: {}
}
});
}
};
```
After (ESM):
```
import { join } from 'path';
import { mergeConfig } from 'vite';
export default {
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials'],
viteFinal: async (config) => {
return mergeConfig(config, {
resolve: {
alias: {}
}
});
}
};
```
## Important Notes
- Preserve all comments in the original files
- Maintain the same indentation and formatting style
- For TypeScript files (.ts), ensure type imports use import type when appropriate
- Test that the transformations don't break the Storybook configuration

View File

@@ -1,5 +1,5 @@
import { getJestProjects } from '@nx/jest';
import { getJestProjectsAsync } from '@nx/jest';
export default {
projects: getJestProjects(),
};
export default async () => ({
projects: await getJestProjectsAsync(),
});

View File

@@ -0,0 +1,42 @@
{
"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,13 @@
# _internal-controllers
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build _internal-controllers` to build the library.
## Running unit tests
Run `nx test _internal-controllers` to execute the unit tests via [Jest](https://jestjs.io).

View File

@@ -0,0 +1,10 @@
{
"name": "@z-elements/_internal/controllers",
"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,45 @@
{
"name": "_internal-controllers",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/_internal/controllers/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/libs/_internal/controllers",
"main": "libs/_internal/controllers/src/index.ts",
"tsConfig": "libs/_internal/controllers/tsconfig.lib.json",
"assets": [
"libs/_internal/controllers/*.md"
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": [
"libs/_internal/controllers/**/*.ts",
"libs/_internal/controllers/package.json"
]
}
},
"test": {
"executor": "@nx/vite:test",
"outputs": [
"{options.reportsDirectory}"
],
"options": {
"passWithNoTests": true,
"reportsDirectory": "../../../coverage/libs/_internal/controllers"
}
}
},
"tags": []
}

View File

@@ -0,0 +1 @@
export * from './lib/destroy.controller';

View File

@@ -0,0 +1,31 @@
import { ReactiveController, ReactiveControllerHost } from 'lit';
import { Subject } from 'rxjs';
export class DestroyController implements ReactiveController {
/** Private variables */
private readonly _host: ReactiveControllerHost;
private readonly destroy$ = new Subject<void>();
/** Protected variables */
/** Public variables */
public readonly destroy = this.destroy$.asObservable();
/** constructor & lifecycle */
constructor(host: ReactiveControllerHost) {
this._host = host;
this._host.addController(this);
}
public hostDisconnected() {
this.destroy$.next();
this.destroy$.complete();
}
/** Public methods */
/** Protected methods */
/** Private methods */
}

View File

@@ -0,0 +1,25 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"types": [
"vitest"
]
},
"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,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"]
},
"include": [
"vite.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
]
}

View File

@@ -0,0 +1,24 @@
/// <reference types="vitest" />
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { defineConfig } from 'vite';
export default defineConfig({
cacheDir: '../../../node_modules/.vite/_internal-controllers',
plugins: [nxViteTsPaths()],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
test: {
reporters: ['default'],
globals: true,
cache: {
dir: '../../../node_modules/.vitest',
},
environment: 'node',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
});

View File

@@ -0,0 +1,42 @@
{
"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,19 @@
# _internal-directives
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build _internal-directives` to build the library.
## Running unit tests
Run `nx test _internal-directives` to execute the unit tests via [Jest](https://jestjs.io).

View File

@@ -0,0 +1,10 @@
{
"name": "@z-elements/_internal/directives",
"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,45 @@
{
"name": "_internal-directives",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/_internal/directives/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/libs/_internal/directives",
"main": "libs/_internal/directives/src/index.ts",
"tsConfig": "libs/_internal/directives/tsconfig.lib.json",
"assets": [
"libs/_internal/directives/*.md"
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": [
"libs/_internal/directives/**/*.ts",
"libs/_internal/directives/package.json"
]
}
},
"test": {
"executor": "@nx/vite:test",
"outputs": [
"{options.reportsDirectory}"
],
"options": {
"passWithNoTests": true,
"reportsDirectory": "../../../coverage/libs/_internal/directives"
}
}
},
"tags": []
}

View File

@@ -0,0 +1 @@
export { asyncDirective } from './lib/async-directive';

View File

@@ -0,0 +1,41 @@
import { noChange } from 'lit';
import { AsyncDirective, directive } from 'lit/async-directive.js';
import { Observable, Subject, takeUntil, tap } from 'rxjs';
class Async extends AsyncDirective {
/** Private variables */
private readonly destroy$ = new Subject<void>();
/** Protected variables */
/** Public variables */
/** constructor & lifecycle */
protected override disconnected(): void {
super.disconnected();
this.destroy$.next();
this.destroy$.complete();
}
/** Public methods */
render(observable: Observable<unknown>) {
observable
.pipe(
takeUntil(this.destroy$),
tap((value: unknown) => {
this.setValue(value);
}),
)
.subscribe();
return noChange;
}
/** Protected methods */
/** Private methods */
}
export const asyncDirective = directive(Async);

View File

@@ -0,0 +1,25 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"types": [
"vitest"
]
},
"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,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"]
},
"include": [
"vite.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
]
}

View File

@@ -0,0 +1,24 @@
/// <reference types="vitest" />
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { defineConfig } from 'vite';
export default defineConfig({
cacheDir: '../../../node_modules/.vite/_internal-directives',
plugins: [nxViteTsPaths()],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
test: {
reporters: ['default'],
globals: true,
cache: {
dir: '../../../node_modules/.vitest',
},
environment: 'node',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
});

View File

@@ -1,5 +1,5 @@
{
"name": "z-styles",
"name": "@hijlkema-codes/internal/z-styles",
"version": "0.0.1",
"dependencies": {
"tslib": "^2.3.0"

View File

@@ -3,6 +3,7 @@
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/_internal/styles/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
@@ -18,10 +19,7 @@
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": [
"libs/_internal/styles/**/*.ts",
"libs/_internal/styles/package.json"
]
"lintFilePatterns": ["libs/_internal/styles/**/*.ts", "libs/_internal/styles/package.json"]
}
},
"test": {
@@ -38,6 +36,5 @@
}
}
}
},
"tags": []
}
}

View File

@@ -1,3 +1,5 @@
export * from './lib/normalize';
export { normalize } from './lib/normalize';
export * from './lib/variable.helper';
export { VariableHelper } from './lib/variable.helper';
export { variable } from './lib/variable.func';

View File

@@ -0,0 +1,5 @@
import { unsafeCSS } from 'lit';
export function variable(variableName: `--${string}`, defaultValue?: string) {
return unsafeCSS(`var(${variableName}${defaultValue ? `, ${defaultValue}` : ''})`);
}

View File

@@ -0,0 +1,42 @@
{
"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,13 @@
# _internal-types
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build _internal-types` to build the library.

View File

@@ -0,0 +1,10 @@
{
"name": "@z-elements/_internal/types",
"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,35 @@
{
"name": "_internal-types",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/_internal/types/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/libs/_internal/types",
"main": "libs/_internal/types/src/index.ts",
"tsConfig": "libs/_internal/types/tsconfig.lib.json",
"assets": [
"libs/_internal/types/*.md"
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": [
"libs/_internal/types/**/*.ts",
"libs/_internal/types/package.json"
]
}
}
},
"tags": []
}

View File

@@ -0,0 +1 @@
export * from './lib/lit'

View File

@@ -0,0 +1,5 @@
import { ReactiveControllerHost as LitReactiveControllerHost } from 'lit';
export type ReactiveControllerHost<T> = LitReactiveControllerHost & {
[K in keyof T]: T[K];
};

View File

@@ -0,0 +1,19 @@
{
"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"
}
]
}

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

@@ -3,6 +3,7 @@
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/accordion/src",
"projectType": "library",
"tags": ["type:component", ""],
"targets": {
"build": {
"executor": "@nx/vite:build",
@@ -19,10 +20,7 @@
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": [
"libs/accordion/**/*.ts",
"libs/accordion/package.json"
]
"lintFilePatterns": ["libs/accordion/**/*.ts", "libs/accordion/package.json"]
}
},
"test": {
@@ -39,6 +37,5 @@
}
}
}
},
"tags": ["type:component", ""]
}
}

View File

@@ -1,5 +1,6 @@
import { LitElement, TemplateResult, html } from 'lit';
import { customElement, queryAssignedElements } from 'lit/decorators.js';
import { customElement, property, queryAssignedElements } from 'lit/decorators.js';
import AccordionComponent from './accordion.component';
@customElement('z-accordion.group')
@@ -7,22 +8,19 @@ export default class AccordionGroupComponent extends LitElement {
@queryAssignedElements({ selector: 'z-accordion' })
public items!: NodeListOf<AccordionComponent>;
@property({ type: Boolean })
public closeOthers: boolean = false;
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;
}
});
if (this.closeOthers) {
this.items.forEach((i: AccordionComponent) => {
if (i !== item) {
i.open = false;
}
});
}
});
});
}

View File

@@ -0,0 +1,42 @@
{
"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,35 @@
import type { StorybookConfig } from '@storybook/web-components-vite';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { mergeConfig } from 'vite';
const config: StorybookConfig = {
stories: [
'../src/lib/**/*.stories.@(js|jsx|ts|tsx|mdx)'
],
addons: ['@storybook/addon-essentials' , '@storybook/addon-interactions' ],
framework: {
name: '@storybook/web-components-vite',
options: {
},
},
viteFinal: async (config) =>
mergeConfig(config, {
plugins: [nxViteTsPaths()],
}),
};
export default config;
// To customize your Vite configuration you can use the viteFinal field.
// Check https://storybook.js.org/docs/react/builders/vite#configuration
// and https://nx.dev/packages/storybook/documents/custom-builder-configs

13
libs/container/README.md Normal file
View File

@@ -0,0 +1,13 @@
# container
> !note: this needs to be imported from stackblitz
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build container` to build the library.
## Running unit tests
Run `nx test container` to execute the unit tests via [Jest](https://jestjs.io).

View File

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

View File

@@ -0,0 +1,10 @@
{
"name": "@z-elements/container",
"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,71 @@
{
"name": "container",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/container/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/container",
"main": "libs/container/src/index.ts",
"tsConfig": "libs/container/tsconfig.lib.json",
"assets": ["libs/container/*.md"]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/container/**/*.ts", "libs/container/package.json"]
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/container/jest.config.ts",
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
},
"storybook": {
"executor": "@nx/storybook:storybook",
"options": {
"port": 4400,
"configDir": "libs/container/.storybook"
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"build-storybook": {
"executor": "@nx/storybook:build",
"outputs": ["{options.outputDir}"],
"options": {
"outputDir": "dist/storybook/container",
"configDir": "libs/container/.storybook"
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"test-storybook": {
"executor": "nx:run-commands",
"options": {
"command": "test-storybook -c libs/container/.storybook --url=http://localhost:4400"
}
}
}
}

View File

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

View File

@@ -0,0 +1,45 @@
import { Meta, StoryObj } from '@storybook/web-components';
import { html } from 'lit';
import './container.component';
import { Container } from './container.component';
const meta: Meta<Container> = {
title: 'Design System/Atoms/Container',
component: 'z-container',
args: {
conditionalRadius: true,
radius: '12px',
},
render: (args) => html`
<style>
html {
background-color: #e2e2e2;
--container--background-color: #fff;
--container--max-width: 80rem;
}
</style>
<z-container radius="${args['radius']}" ?conditional-radius="${args['conditionalRadius']}">
<div style="display: flex; column-gap: 3.5rem; padding-left: 3.5rem;">
<p style="margin: 0; padding-block: 3.5rem">
Incididunt voluptate non ea reprehenderit quis nostrud proident pariatur enim mollit esse nulla. Ex mollit mollit occaecat esse
consequat. Tempor dolor irure qui dolor proident esse voluptate excepteur dolor. Pariatur aliqua exercitation Lorem Lorem irure
occaecat amet est in nulla eu.
</p>
<img src="https://placeholder.co/350" alt="" />
</div>
</z-container>
`,
parameters: {
layout: 'fullscreen',
},
} satisfies Meta;
export default meta;
type Story = StoryObj<unknown>;
export const Primary: Story = {};

View File

@@ -0,0 +1,99 @@
import { LitElement, PropertyValues, css, html, unsafeCSS } from 'lit';
import { customElement, property } from 'lit/decorators.js';
/**
* A container element that centers its content and has a max-width.
*
* @slot - The default slot.
* @slot img - The slot for the image.
*
* @cssproperty --container--max-width - The max-width of the container.
* @cssproperty --container--background-color - The background color of the container.
*/
@customElement('z-container')
export class Container extends LitElement {
/// Private variables ///
/// Protected variables ///
/// Public variables ///
@property() public radius: string | undefined;
@property({ type: Boolean, attribute: 'conditional-radius' }) public conditionalRadius: boolean = false;
/// constructor & lifecycle ///
protected override willUpdate(_changedProperties: PropertyValues): void {
super.willUpdate(_changedProperties);
this.updateBorderRadius();
}
/// Public methods ///
/// Protected methods ///
protected override render(): unknown {
return html`
<section>
<slot></slot>
<slot name="img"></slot>
</section>
`;
}
/// Private methods ///
private updateBorderRadius(): void {
const hasRadius = !!this.radius;
const isConditional = this.conditionalRadius;
switch (true) {
case !hasRadius:
this.removeBorderRadius();
break;
case hasRadius && isConditional:
this.setConditionRadius();
break;
case hasRadius && !isConditional:
this.setRadius();
break;
}
}
private removeBorderRadius(): void {
this.style.removeProperty(Container.CSS_PROPERTY_NAMES.RADIUS);
}
private setConditionRadius(): void {
if (this.radius) {
this.style.setProperty(Container.CSS_PROPERTY_NAMES.RADIUS, `max(0px, min(${this.radius}, calc((100vw - 4px - 100%) * 9999)))`);
}
}
private setRadius(): void {
if (this.radius) {
this.style.setProperty(Container.CSS_PROPERTY_NAMES.RADIUS, this.radius);
}
}
/// Statics ///
static CSS_PROPERTY_NAMES = {
RADIUS: '--container--radius',
BACKGROUND_COLOR: '--container--background-color',
MAX_WIDTH: '--container--max-width',
};
static override get styles() {
return [
css`
:host {
width: 100%;
max-width: var(${unsafeCSS(Container.CSS_PROPERTY_NAMES.MAX_WIDTH)}, 80rem);
margin-inline: auto;
display: flex;
background-color: var(${unsafeCSS(Container.CSS_PROPERTY_NAMES.BACKGROUND_COLOR)});
border-radius: var(${unsafeCSS(Container.CSS_PROPERTY_NAMES.RADIUS)}, 0px);
overflow: hidden;
}
`,
];
}
}

View File

@@ -0,0 +1,7 @@
import { container } from './container';
describe('container', () => {
it('should work', () => {
expect(container()).toEqual('container');
});
});

View File

@@ -0,0 +1,25 @@
{
"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"
},
{
"path": "./tsconfig.storybook.json"
}
]
}

View File

@@ -0,0 +1,20 @@
{
"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",
"**/*.stories.ts",
"**/*.stories.js"
]
}

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,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDecoratorMetadata": true
},
"exclude": [
"src/**/*.spec.ts",
"src/**/*.test.ts"
],
"include": [
"src/**/*.stories.ts",
"src/**/*.stories.js",
"src/**/*.stories.jsx",
"src/**/*.stories.tsx",
"src/**/*.stories.mdx",
".storybook/*.js",
".storybook/*.ts"
]
}

View File

@@ -0,0 +1,42 @@
{
"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,16 @@
import type { StorybookConfig } from '@storybook/web-components-vite';
const config: StorybookConfig = {
stories: ['../src/lib/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'],
framework: {
name: '@storybook/web-components-vite',
options: {},
},
};
export default config;
// To customize your webpack configuration you can use the webpackFinal field.
// Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config
// and https://nx.dev/packages/storybook/documents/custom-builder-configs

View File

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

View File

@@ -0,0 +1,10 @@
{
"name": "@z-elements/panels/bottom-panel",
"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,78 @@
{
"name": "panels-bottom-panel",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/panels/bottom-panel/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/libs/panels/bottom-panel",
"main": "libs/panels/bottom-panel/src/index.ts",
"tsConfig": "libs/panels/bottom-panel/tsconfig.lib.json",
"assets": [
"libs/panels/bottom-panel/*.md"
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": [
"libs/panels/bottom-panel/**/*.ts",
"libs/panels/bottom-panel/package.json"
]
}
},
"test": {
"executor": "@nx/vite:test",
"outputs": [
"{workspaceRoot}/coverage/libs/panels/bottom-panel"
],
"options": {
"passWithNoTests": true,
"reportsDirectory": "../../../coverage/libs/panels/bottom-panel"
}
},
"storybook": {
"executor": "@nx/storybook:storybook",
"options": {
"port": 4400,
"configDir": "libs/panels/bottom-panel/.storybook"
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"build-storybook": {
"executor": "@nx/storybook:build",
"outputs": [
"{options.outputDir}"
],
"options": {
"outputDir": "dist/storybook/panels-bottom-panel",
"configDir": "libs/panels/bottom-panel/.storybook"
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"test-storybook": {
"executor": "nx:run-commands",
"options": {
"command": "test-storybook -c libs/panels/bottom-panel/.storybook --url=http://localhost:4400"
}
}
},
"tags": []
}

View File

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

View File

@@ -0,0 +1,104 @@
import { Meta, StoryObj } from '@storybook/web-components';
import { html } from 'lit';
import './bottom-panel.component';
import BottomPanel from './bottom-panel.component';
export default {
title: 'Design System/Atoms/Panels/Bottom',
component: 'z-panels.bottom',
render: (args) => html`
<style>
html {
background-color: #ccc;
}
</style>
<z-panels.bottom ?open=${args.open}>
<div slot="header">
<h2>est excepteur ea irure elit</h2>
</div>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
<p>
Esse laborum pariatur irure in consequat deserunt officia. Eu aliquip ad duis. Voluptate velit fugiat ex Lorem et. Ea laborum ut
veniam est ad consequat pariatur.
</p>
</z-panels.bottom>
`,
parameters: {
layout: 'fullscreen',
},
argTypes: {
open: {
control: 'boolean',
},
},
args: {
open: false,
},
} satisfies Meta<BottomPanel>;
type Story = StoryObj<BottomPanel>;
export const Primary: Story = {};

View File

@@ -0,0 +1,63 @@
import { DestroyController } from '@z-elements/_internal/controllers';
import { LitElement, PropertyValues, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { filter, fromEvent, takeUntil, tap } from 'rxjs';
import { hostStyles, panelStyles } from './styles';
@customElement('z-panels.bottom')
export default class BottomPanel extends LietElement {
static override get styles() {
return [hostStyles, panelStyles];
}
/** Private variables */
private readonly _destroyController = new DestroyController(this);
private readonly _closeEvent = new CustomEvent('close', { bubbles: false });
/** Protected variables */
/** Public variables */
@property({ type: Boolean, reflect: true }) public open = false;
/** constructor & lifecycle */
override connectedCallback() {
super.connectedCallback();
fromEvent<MouseEvent>(this, 'click')
.pipe(
filter(() => this.open),
filter((event: MouseEvent) => event.target === this),
tap(() => {
this.open = false;
this.dispatchEvent(this._closeEvent);
}),
takeUntil(this._destroyController.destroy),
)
.subscribe();
}
override updated(changedProperties: PropertyValues) {
super.updated(changedProperties);
this.shadowRoot?.querySelector('aside')?.scrollTo(0, 0);
}
/** Public methods */
/** Protected methods */
protected override render(): unknown {
return html`
<aside>
<header><slot name="header"></slot></header>
<slot></slot>
</aside>
`;
}
/** Private methods */
}

View File

@@ -0,0 +1,55 @@
import { variable } from '@hijlkema-codes/internal/z-styles';
import { css } from 'lit';
import { backgroundColor, borderRadius, maxHeight, padding } from './variables';
export const hostStyles = css`
:host {
display: block;
overflow: hidden;
position: fixed;
inset: 0;
pointer-events: none;
z-index: ${Number.MAX_SAFE_INTEGER};
}
:host([open]) {
pointer-events: auto;
}
:host(:not([open])) aside {
transform: translateY(100vh);
}
:host([open]) aside {
transform: translateY(0);
transition-timing-function: ease-in;
}
:host(:not([open])) aside::before {
opacity: 0;
}
:host([open]) aside {
opacity: 1;
transition-timing-function: ease-in;
}
`;
export const panelStyles = css`
aside {
position: absolute;
background-color: ${variable(backgroundColor, 'hsl(0, 100%, 100%)')};
box-shadow: 0 -3px 6px rgba(0, 0, 0, 0.04);
border-radius: ${variable(borderRadius, '.75rem .75rem 0 0')};
padding: ${variable(padding, '2rem 1.5rem')};
inset-inline: 0;
bottom: 0;
max-height: ${variable(maxHeight, '60vh')};
pointer-events: auto;
transition: transform 0.3s ease-out;
overflow: scroll;
scroll-behavior: smooth;
}
`;

View File

@@ -0,0 +1,4 @@
export const borderRadius = '--z-panels--bottom-panel--border-radius';
export const backgroundColor = '--z-panels--bottom-panel--background-color';
export const padding = '--z-panels--bottom-panel--padding';
export const maxHeight = '--z-panels--bottom-panel--max-height';

View File

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

View File

@@ -0,0 +1,20 @@
{
"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",
"**/*.stories.ts",
"**/*.stories.js"
]
}

View File

@@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"]
},
"include": [
"vite.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
]
}

View File

@@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDecoratorMetadata": true
},
"exclude": [
"src/**/*.spec.ts",
"src/**/*.test.ts"
],
"include": [
"src/**/*.stories.ts",
"src/**/*.stories.js",
"src/**/*.stories.jsx",
"src/**/*.stories.tsx",
"src/**/*.stories.mdx",
".storybook/*.js",
".storybook/*.ts"
]
}

View File

@@ -0,0 +1,24 @@
/// <reference types="vitest" />
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { defineConfig } from 'vite';
export default defineConfig({
cacheDir: '../../../node_modules/.vite/panels-bottom-panel',
plugins: [nxViteTsPaths()],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
test: {
reporters: ['default'],
globals: true,
cache: {
dir: '../../../node_modules/.vitest',
},
environment: 'node',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
});

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 @@
# panels-side-panel
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build panels-side-panel` to build the library.
## Running unit tests
Run `nx test panels-side-panel` to execute the unit tests via [Jest](https://jestjs.io).

View File

@@ -0,0 +1,10 @@
{
"name": "@z-elements/panels/side-panel",
"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,45 @@
{
"name": "panels-side-panel",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/panels/side-panel/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/libs/panels/side-panel",
"main": "libs/panels/side-panel/src/index.ts",
"tsConfig": "libs/panels/side-panel/tsconfig.lib.json",
"assets": [
"libs/panels/side-panel/*.md"
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": [
"libs/panels/side-panel/**/*.ts",
"libs/panels/side-panel/package.json"
]
}
},
"test": {
"executor": "@nx/vite:test",
"outputs": [
"{workspaceRoot}/coverage/libs/panels/side-panel"
],
"options": {
"passWithNoTests": true,
"reportsDirectory": "../../../coverage/libs/panels/side-panel"
}
}
},
"tags": []
}

View File

@@ -0,0 +1 @@
export * from './lib/panels-side-panel';

View File

@@ -0,0 +1,7 @@
import { SidePanel } from './panels-side-panel';
describe('panelsSidePanel', () => {
it('should work', () => {
expect(SidePanel()).toEqual('panels-side-panel');
});
});

View File

@@ -0,0 +1,28 @@
import { DestroyController } from '@z-elements/_internal/controllers';
import { LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';
@customElement('z-panels.side')
export class SidePanel extends LitElement {
static override get styles() {
return [];
}
/** Private variables */
private readonly _destroyController = new DestroyController(this);
private readonly _closeEvent = new CustomEvent('close', { bubbles: false });
/** Protected variables */
/** Public variables */
/** constructor & lifecycle */
/** Public methods */
/** Protected methods */
/** Private methods */
}

View File

@@ -0,0 +1,23 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"types": ["vitest"]
},
"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,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"]
},
"include": [
"vite.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
]
}

View File

@@ -0,0 +1,24 @@
/// <reference types="vitest" />
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { defineConfig } from 'vite';
export default defineConfig({
cacheDir: '../../../node_modules/.vite/panels-side-panel',
plugins: [nxViteTsPaths()],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
test: {
reporters: ['default'],
globals: true,
cache: {
dir: '../../../node_modules/.vitest',
},
environment: 'node',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
});

View File

@@ -0,0 +1,25 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*", "storybook-static"],
"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,34 @@
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import type { StorybookConfig } from '@storybook/web-components-vite';
import { mergeConfig } from 'vite';
// These options were migrated by @nx/storybook:convert-to-inferred from the project.json file.
const configValues = { default: {}, ci: {} };
// Determine the correct configValue to use based on the configuration
const nxConfiguration = process.env.NX_TASK_TARGET_CONFIGURATION ?? 'default';
const options = {
...configValues.default,
...(configValues[nxConfiguration] ?? {}),
};
const config: StorybookConfig = {
stories: ['../src/lib/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'],
framework: {
name: '@storybook/web-components-vite',
options: {},
},
viteFinal: async (config) =>
mergeConfig(config, {
plugins: [nxViteTsPaths()],
}),
};
export default config;
// To customize your Vite configuration you can use the viteFinal field.
// Check https://storybook.js.org/docs/react/builders/vite#configuration
// and https://nx.dev/recipes/storybook/custom-builder-configs

View File

View File

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

View File

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

View File

@@ -0,0 +1,11 @@
{
"name": "@z-elements/reviews-stars",
"version": "0.0.1",
"dependencies": {
"tslib": "^2.3.0"
},
"type": "commonjs",
"main": "./src/index.js",
"typings": "./src/index.d.ts",
"private": true
}

View File

@@ -0,0 +1,64 @@
{
"name": "reviews-stars",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/reviews-stars/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/reviews-stars",
"main": "libs/reviews-stars/src/index.ts",
"tsConfig": "libs/reviews-stars/tsconfig.lib.json",
"assets": ["libs/reviews-stars/*.md"]
}
},
"lint": {
"executor": "@nx/eslint:lint"
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/reviews-stars/jest.config.ts"
}
},
"storybook": {
"options": {
"port": 4400,
"config-dir": ".storybook"
},
"configurations": {
"ci": {
"args": ["--quiet"]
}
}
},
"build-storybook": {
"outputs": [
"{projectRoot}/{options.output-dir}",
"{workspaceRoot}/{projectRoot}/storybook-static",
"{options.output-dir}",
"{options.outputDir}",
"{options.o}"
],
"options": {
"config-dir": ".storybook",
"output-dir": "../../dist/storybook/reviews-stars"
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"test-storybook": {
"executor": "nx:run-commands",
"options": {
"command": "test-storybook -c libs/reviews-stars/.storybook --url=http://localhost:4400"
}
}
}
}

View File

@@ -0,0 +1 @@
export * from './lib/reviews-stars';

View File

@@ -0,0 +1,53 @@
import { Meta, StoryObj } from '@storybook/web-components';
import { html } from 'lit';
import './reviews-stars';
import { ReviewsStarsComponent } from './reviews-stars';
const meta: Meta<ReviewsStarsComponent> = {
title: 'Design System/Atoms/Reviews Stars',
component: 'z-reviews.stars',
render: (args) => html`
<z-reviews.stars
?allow-fractional="${args.allowFractional}"
rating="${args.rating}"
out-of="${args.outOf}"
.stars=${args.stars}
></z-reviews.stars>
`,
parameters: {
layout: 'centered',
},
argTypes: {
rating: {
control: 'number',
min: 1,
},
outOf: {
control: {
type: 'number',
min: 1,
},
},
stars: {
control: {
type: 'number',
min: 1,
},
},
allowFractional: {
control: 'boolean',
},
},
args: {
rating: 3,
outOf: 5,
stars: 5,
allowFractional: false,
},
};
export default meta;
export const Primary: StoryObj<ReviewsStarsComponent> = {};

View File

@@ -0,0 +1,140 @@
import { css, CSSResultArray, html, LitElement, TemplateResult } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
/**
* @cssprop --filled-star-color - The color of the filled stars.
* @cssprop --empty-star-color - The color of the empty stars.
*/
@customElement('z-reviews.stars')
export class ReviewsStarsComponent extends LitElement {
/// Private variables ///
/// Protected variables ///
@state() protected _filledStarCount = 0;
/// Public variables ///
@property({ type: Number }) public rating: number | undefined;
@property({ type: Number, attribute: 'out-of' }) public outOf: number | undefined;
@property({ type: Number }) public stars: number = 5;
@property({ type: Boolean, attribute: 'allow-fractional' }) public allowFractional = false;
/// constructor & lifecycle ///
override connectedCallback(): void {
super.connectedCallback();
this.validateProperties();
}
override updated(changedProperties: Map<string | number | symbol, unknown>): void {
super.updated(changedProperties);
this._filledStarCount = this.calculateFilledStarCount();
// this.requestUpdate();
}
/// Public methods ///
/// Protected methods ///
protected override render(): TemplateResult {
return html`
<div class="stars">${this.renderStars()}</div>
<div
class="stars stars--filled"
style="${styleMap({
'--filled-star-count': this._filledStarCount,
'--_filled-star-width': `${(this._filledStarCount / this.stars) * 100}%`,
})}"
>
${this.renderStars()}
</div>
`;
}
protected renderStars(): TemplateResult {
const stars: TemplateResult[] = [];
for (let i = 0; i < this.stars; i++) {
stars.push(this.renderStar());
}
return html`${stars}`;
}
protected renderStar(): TemplateResult {
return html`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="icon">
<!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.-->
<path
d="M316.9 18C311.6 7 300.4 0 288.1 0s-23.4 7-28.8 18L195 150.3 51.4 171.5c-12 1.8-22 10.2-25.7 21.7s-.7 24.2 7.9 32.7L137.8 329 113.2 474.7c-2 12 3 24.2 12.9 31.3s23 8 33.8 2.3l128.3-68.5 128.3 68.5c10.8 5.7 23.9 4.9 33.8-2.3s14.9-19.3 12.9-31.3L438.5 329 542.7 225.9c8.6-8.5 11.7-21.2 7.9-32.7s-13.7-19.9-25.7-21.7L381.2 150.3 316.9 18z"
/>
</svg>
</svg>`;
}
/// Private methods ///
/**
* Validate the properties for the rules of availability.
*
* @throws {Error} If the properties are not valid.
*/
private validateProperties(): void {
console.log(this.rating, this.stars, this.outOf, this.allowFractional);
if (!this.rating) {
throw new Error('Rating is required.');
}
if (!this.outOf) {
throw new Error('Out of is required when rating is used.');
}
if (this.stars < 1) {
throw new Error('Stars cannot be less than 1.');
}
if (this.rating! > this.outOf) {
throw new Error('Rating cannot be greater than out of.');
}
}
private calculateFilledStarCount(): number {
if (this.allowFractional) {
return (this.rating! / this.outOf!) * this.stars;
}
return Math.round((this.rating! / this.outOf!) * this.stars);
}
/// Statics ///
static override styles: CSSResultArray = [
css`
:host {
display: flex;
position: relative;
}
.icon {
vertical-align: -0.125em;
flex: 0 0 1em;
height: 1em;
width: 1em;
fill: currentColor;
}
.stars {
display: flex;
color: var(--empty-star-color, #e4e5e9);
}
.stars--filled {
position: absolute;
top: 0;
left: 0;
overflow: hidden;
opacity: 1;
right: calc(100% - var(--_filled-star-width));
color: var(--filled-star-color, #f7b731);
}
`,
];
}

View File

@@ -0,0 +1,25 @@
{
"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"
},
{
"path": "./tsconfig.storybook.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", "**/*.stories.ts", "**/*.stories.js"]
}

View File

@@ -0,0 +1,9 @@
{
"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,16 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDecoratorMetadata": true
},
"exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"],
"include": [
"src/**/*.stories.ts",
"src/**/*.stories.js",
"src/**/*.stories.jsx",
"src/**/*.stories.tsx",
"src/**/*.stories.mdx",
".storybook/*.js",
".storybook/*.ts"
]
}

View File

@@ -0,0 +1,42 @@
{
"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"
}
}
]
}

Some files were not shown because too many files have changed in this diff Show More