diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2fd10c0..3918484 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,54 +57,6 @@ jobs: npm install -g npm@11.7.0 npm -v - - name: Diagnostic info - run: | - echo "node=$(node -v)" - echo "npm=$(npm -v)" - if [ -n "${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" ]; then - echo "oidc=available" - else - echo "oidc=missing" - fi - - - name: Inspect OIDC claims - run: | - if [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL}" ]; then - echo "OIDC token request env vars are missing" - exit 1 - fi - - RESPONSE="$(curl -sSf -H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=npm:registry.npmjs.org")" - OIDC_TOKEN="$(node -e 'const fs = require("fs"); const input = fs.readFileSync(0, "utf8"); process.stdout.write(JSON.parse(input).value);' <<< "$RESPONSE")" - - node - <<'EOF' "$OIDC_TOKEN" - const token = process.argv[2]; - const payload = token.split(".")[1]; - - if (!payload) { - throw new Error("Unable to decode OIDC token payload"); - } - - const claims = JSON.parse(Buffer.from(payload, "base64url").toString("utf8")); - const out = { - aud: claims.aud, - repository: claims.repository, - repository_owner: claims.repository_owner, - ref: claims.ref, - sha: claims.sha, - event_name: claims.event_name, - workflow: claims.workflow, - workflow_ref: claims.workflow_ref, - job_workflow_ref: claims.job_workflow_ref, - runner_environment: claims.runner_environment, - environment: claims.environment, - actor: claims.actor, - sub: claims.sub, - }; - - console.log(JSON.stringify(out, null, 2)); - EOF - - name: Install dependencies run: npm ci diff --git a/.gitignore b/.gitignore index 676f768..86f483e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ lerna-debug.log* node_modules dist dist-types +coverage addon storybook-static .adnbn diff --git a/.release-it.cjs b/.release-it.cjs index d3899e6..d6184e0 100644 --- a/.release-it.cjs +++ b/.release-it.cjs @@ -107,7 +107,71 @@ const types = new Map([ const normalizeRepoUrl = url => url.replace(/^git\+/, "").replace(/\.git$/, ""); const repoUrl = pkg?.repository?.url ? normalizeRepoUrl(pkg.repository.url) : null; -module.exports = () => { +const breakingChangePattern = /\bBREAKING(?: |-)?CHANGE\b/i; + +function hasBreakingChange(commit) { + if (commit.breaking) { + return true; + } + + const type = String(commit.type || "").trim(); + + if (type.endsWith("!")) { + return true; + } + + if (typeof commit.header === "string" && /^\w+(?:\([^)]+\))?!:/.test(commit.header)) { + return true; + } + + if ( + commit.notes?.some(note => + [note.title, note.text].some(value => typeof value === "string" && breakingChangePattern.test(value)) + ) + ) { + return true; + } + + return typeof commit.footer === "string" && breakingChangePattern.test(commit.footer); +} + +function whatBump(commits, currentVersion = pkg.version) { + let isBreaking = false; + let isMinor = false; + let isPatch = false; + + for (const commit of commits) { + if (hasBreakingChange(commit)) { + isBreaking = true; + } + + const type = String(commit.type || "") + .trim() + .toLowerCase() + .replace(/!+$/, ""); + + if (type === "feat") { + isMinor = true; + } + + if (["fix", "perf", "refactor", "ci"].includes(type)) { + isPatch = true; + } + } + + if (isBreaking) { + const currentMajor = Number.parseInt(String(currentVersion).replace(/^v/i, "").split(".")[0], 10); + + return {level: Number.isNaN(currentMajor) || currentMajor >= 1 ? 0 : 1}; + } + + if (isMinor) return {level: 1}; + if (isPatch) return {level: 2}; + + return null; +} + +const createReleaseConfig = () => { const contributors = getContributors(); return { @@ -151,14 +215,6 @@ module.exports = () => { presetConfig: { types: [...types.entries()].map(([type, section]) => ({type, section, hidden: false})), - releaseRules: [ - {breaking: true, release: "major"}, - {type: "feat", release: "minor"}, - {type: "fix", release: "patch"}, - {type: "perf", release: "patch"}, - {type: "refactor", release: "patch"}, - {type: "ci", release: "patch"}, - ], }, context: { @@ -168,39 +224,7 @@ module.exports = () => { contributors, }, - recommendedBump: true, - whatBump: commits => { - let isMajor = false; - let isMinor = false; - let isPatch = false; - - for (const commit of commits) { - const hasBreaking = - Boolean(commit.breaking) || - (commit.notes && - commit.notes.some(n => /BREAKING[ -]CHANGE/i.test(n.title || n.text || ""))); - if (hasBreaking) { - isMajor = true; - break; - } - - const type = (commit.type || "").toLowerCase().replace(/!+$/, ""); - - if (type === "feat") { - isMinor = true; - } - - if (["fix", "perf", "refactor", "ci"].includes(type)) { - isPatch = true; - } - } - - if (isMajor) return {level: 0}; - if (isMinor) return {level: 1}; - if (isPatch) return {level: 2}; - - return null; - }, + whatBump, writerOpts: { headerPartial: "## πŸš€ Release {{#if name}}`{{name}}` {{else}}{{#if @root.pkg}}`{{@root.pkg.name}}` {{/if}}{{/if}}v{{version}} ({{date}})\n\n", @@ -259,3 +283,5 @@ module.exports = () => { }, }; }; + +module.exports = Object.assign(createReleaseConfig, {whatBump}); diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f08e7d3 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,41 @@ +# Contributing to addon-ui + +## Workflow + +- Create feature branches from `develop` and open pull requests back into `develop`. +- Merge the intended release changes from `develop` into `main`. +- A push to `main` runs the release workflow, which creates the version commit, tag, GitHub Release, npm publication, and + sync back to `develop`. + +## Commit messages + +Use Conventional Commits: + +```text +(): +``` + +Mark a breaking change with `!` after the type/scope, or with a `BREAKING CHANGE:` or `BREAKING-CHANGE:` footer. + +```text +refactor!: remove deprecated API + +BREAKING CHANGE: Consumers must use the replacement API. +``` + +## Version policy + +Release-it derives the next version from commit history. The highest applicable bump wins. + +- Before `1.0.0`, a breaking change produces a minor release (`0.y.0`). +- Starting at `1.0.0`, a breaking change produces a major release (`x.0.0`). +- `feat` produces a minor release. +- `fix`, `perf`, `refactor`, and `ci` produce a patch release. +- `docs`, `test`, `chore`, and `build` do not produce a release on their own. + +## Documentation and validation + +- Keep canonical user documentation in `docs/` in sync with public props and CSS variables. +- Update Storybook stories when a visual component change needs review. +- Before opening a pull request, run the relevant checks: `npm run lint`, `npm run typecheck`, `npm test`, and + `npm run build:types`. diff --git a/README.md b/README.md index 88ebbed..40eb0c2 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,17 @@ # addon-ui -[![npm version](https://img.shields.io/npm/v/addon-ui.svg)](https://www.npmjs.com/package/addon-ui) -[![npm downloads](https://img.shields.io/npm/dm/addon-ui.svg)](https://www.npmjs.com/package/addon-ui) -[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) +A React UI toolkit for Addon Bone browser-extension applications. -Addon UI - A comprehensive UI component library designed for the Addon Bone framework. -This library provides a set of customizable React components with theming capabilities to build modern, -responsive user interfaces. +[![npm version](https://img.shields.io/npm/v/addon-ui.svg?logo=npm&style=for-the-badge)](https://www.npmjs.com/package/addon-ui) +[![npm downloads](https://img.shields.io/npm/dm/addon-ui.svg?style=for-the-badge&color=blue)](https://www.npmjs.com/package/addon-ui) +[![CI](https://img.shields.io/github/actions/workflow/status/addon-stack/addon-ui/ci.yml?branch=develop&style=for-the-badge)](https://github.com/addon-stack/addon-ui/actions/workflows/ci.yml) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](LICENSE.md) -## Features +Build consistent browser-extension interfaces with React components, typed UI +configuration, theme customization, and an Addon Bone plugin for shared and +app-specific UI files. + +## Why addon-ui - 🎨 **Customizable Theming**: Easily customize the look and feel of components through theme configuration - 🧩 **Rich Component Set**: Includes buttons, forms, layouts, modals, and more @@ -18,9 +21,11 @@ responsive user interfaces. ## Table of Contents +- [Why addon-ui](#why-addon-ui) - [Installation](#installation) +- [Quick Start](#quick-start) +- [Package Entry Points](#package-entry-points) - [Components](#components) -- [Basic Usage](#basic-usage) - [Integration](#integration) - [Customization](#customization) - [Using Extra Props](#using-extra-props) @@ -32,24 +37,53 @@ responsive user interfaces. ## Installation -### npm: +`addon-ui` is designed to be used with [Addon Bone](https://addonbone.com). Your host application must provide +compatible `adnbn`, `react`, and `react-dom` peer dependencies. ```bash -npm install addon-ui +npm i addon-ui ``` -### pnpm: +With pnpm or Yarn: ```bash pnpm add addon-ui +yarn add addon-ui ``` -### yarn: +## Quick Start -```bash -yarn add addon-ui +```jsx +import React from "react"; +import {Button, ButtonColor, ButtonVariant, TextField, UIProvider} from "addon-ui"; + +function App() { + return ( + +
+ + +
+
+ ); +} + +export default App; ``` +## Package Entry Points + +| Import | Use it for | +| :---------------- | :------------------------------------------------------------ | +| `addon-ui` | React components, UI providers, and theme types. | +| `addon-ui/config` | The typed `defineConfig()` helper for UI configuration files. | +| `addon-ui/plugin` | Addon Bone plugin setup and UI-file discovery. | +| `addon-ui/theme` | Sass mixins for extending theme styles. | + +See [Plugin Setup](#plugin-setup) to connect the package to an Addon Bone application. + ## Components This library now ships with dedicated documentation files for each component in the docs/ directory. Start here: @@ -94,28 +128,6 @@ Notes: .module.scss file. - Where a component wraps a Radix UI primitive, the doc links to the official Radix docs and lists common props. -## Basic Usage - -```jsx -import React from "react"; -import {Button, ButtonColor, ButtonVariant, TextField, UIProvider} from "addon-ui"; - -function App() { - return ( - -
- - -
-
- ); -} - -export default App; -``` - ## Integration **Addon UI** is designed exclusively for the [Addon Bone](https://addonbone.com) framework and does not have a standalone build as it's connected @@ -152,11 +164,11 @@ export default defineConfig({ | Option | Type | Default | Description | | :------------ | :------------------------------------------------- | :------------ | :----------------------------------------------------------------------------------------------------- | | `themeDir` | `string` | `"."` | Directory path where plugin configuration and style files are located. | -| `configName` | `string` | `"config.ui"` | Name of the configuration file. | -| `styleName` | `string` | `"style.ui"` | Name of the SCSS style file. | +| `configName` | `string` | `"ui.config"` | Name of the configuration file. | +| `styleName` | `string` | `"ui.style"` | Name of the SCSS style file. | | `mergeConfig` | `boolean` | `true` | Whether to merge configuration files from different directories. | | `mergeStyles` | `boolean` | `true` | Whether to merge style files from different directories. | -| `splitChunks` | `boolean \| (name: string) => string \| undefined` | `true` | Enables automatic chunk splitting. If a function is provided, it can be used to customize chunk names. | +| `splitChunks` | `boolean \| (name: string) => string \| undefined` | `false` | Enables automatic chunk splitting. If a function is provided, it can be used to customize chunk names. | #### Customizing Chunk Names @@ -508,6 +520,7 @@ for full type safety. ## Contributing +- See [CONTRIBUTING.md](CONTRIBUTING.md) for the branch, commit, and release policy. - Keep canonical end-user documentation in the `docs/` directory. When adding or changing CSS variables in a component’s `*.module.scss`, update the corresponding doc table. - Where a component wraps a Radix primitive, keep the β€œRadix UI props” section in sync if the underlying package diff --git a/docs/Button.md b/docs/Button.md index a9fcdd9..a15a529 100644 --- a/docs/Button.md +++ b/docs/Button.md @@ -33,19 +33,19 @@ export function Example() { Only the prop name, type, and default are listed below. -| Prop | Type | Default | -| ------------------- | ------------------------------------------ | ------------- | -| `variant` | `'contained' \| 'outlined' \| 'text'` | `'contained'` | -| `color` | `'primary' \| 'secondary' \| 'accent'` | β€” | -| `size` | `'small' \| 'medium' \| 'large'` | β€” | -| `radius` | `'small' \| 'medium' \| 'large' \| 'full'` | β€” | -| `before` | `ReactNode` | β€” | -| `after` | `ReactNode` | β€” | -| `beforeClassName` | `string` | β€” | -| `afterClassName` | `string` | β€” | -| `childrenClassName` | `string` | β€” | -| `disabled` | `boolean` | `false` | -| HTML button attrs | all standard `button` attributes | β€” | +| Prop | Type | Default | +| ------------------- | -------------------------------------------------------------- | ------------- | +| `variant` | `'contained' \| 'outlined' \| 'text'` | `'contained'` | +| `color` | `'primary' \| 'secondary' \| 'accent' \| 'error' \| 'success'` | β€” | +| `size` | `'small' \| 'medium' \| 'large'` | β€” | +| `radius` | `'small' \| 'medium' \| 'large' \| 'full'` | β€” | +| `before` | `ReactNode` | β€” | +| `after` | `ReactNode` | β€” | +| `beforeClassName` | `string` | β€” | +| `afterClassName` | `string` | β€” | +| `childrenClassName` | `string` | β€” | +| `disabled` | `boolean` | `false` | +| HTML button attrs | all standard `button` attributes | β€” | Note: Defaults may also be provided globally via theme/config (`UIProvider`, `ui.config.ts`). Local props take precedence over global config. @@ -61,6 +61,8 @@ ButtonVariant.Text; ButtonColor.Primary; ButtonColor.Secondary; ButtonColor.Accent; +ButtonColor.Error; +ButtonColor.Success; // Sizes ButtonSize.Small; @@ -84,21 +86,32 @@ Only variables actually referenced in `src/components/Button/button.module.scss` | `--button-font-weight` | `var(--button-font-weight, 500)` | | `--button-font-size` | `var(--button-font-size, var(--font-size, 14px))` | | `--button-letter-spacing` | `var(--button-letter-spacing, 0.5px)` | -| `--button-line-height` | `var(--button-line-height, var(--line-height, 1 rem))` | +| `--button-line-height` | `var(--button-line-height, var(--line-height, 1rem))` | | `--button-height` | `var(--button-height, 34px)` | | `--button-border-radius` | `var(--button-border-radius, 10px)` | | `--button-padding` | `var(--button-padding, 0 16px)` | +| `--button-speed-color` | `var(--button-speed-color, var(--speed-color))` | +| `--button-speed-border-color` | `var(--button-speed-border-color, var(--speed-color))` | +| `--button-speed-bg` | `var(--button-speed-bg, var(--speed-color))` | +| `--button-speed-transform` | `var(--button-speed-transform, var(--speed-sm))` | | `--button-scale` | `var(--button-scale, 0.98)` | | `--button-disabled-opacity` | `var(--button-disabled-opacity, 0.75)` | -| `--button-contained-text-color` | `var(--button-contained-text-color, var(--bg-primary-color))` | -| `--button-contained-bg-color` | `var(--button-contained-bg-color, var(--text-primary-color))` | +| `--button-contained-text-color` | `var(--button-contained-text-color, var(--text-primary-color))` | +| `--button-contained-bg-color` | `var(--button-contained-bg-color, var(--bg-secondary-color))` | +| `--button-contained-primary-text-color` | `var(--button-contained-primary-text-color, #fff)` | +| `--button-contained-secondary-text-color` | `var(--button-contained-secondary-text-color, #fff)` | +| `--button-contained-accent-text-color` | `var(--button-contained-accent-text-color, #fff)` | +| `--button-contained-error-text-color` | `var(--button-contained-error-text-color, #fff)` | +| `--button-contained-success-text-color` | `var(--button-contained-success-text-color, #fff)` | | `--button-outlined-text-color` | `var(--button-outlined-text-color, var(--text-primary-color))` | | `--button-outlined-border-color` | `var(--button-outlined-border-color, var(--button-outlined-text-color, var(--text-primary-color)))` | | `--button-outlined-bg-color-hover` | none (define in theme) | | `--button-outlined-bg-color-active` | none (define in theme) | -| `--button-outlined-border-primary-color` | none (define in theme) | -| `--button-outlined-border-secondary-color` | none (define in theme) | -| `--button-outlined-border-accent-color` | none (define in theme) | +| `--button-outlined-border-primary-color` | `var(--button-outlined-border-primary-color, var(--primary-color))` | +| `--button-outlined-border-secondary-color` | `var(--button-outlined-border-secondary-color, var(--secondary-color))` | +| `--button-outlined-border-accent-color` | `var(--button-outlined-border-accent-color, var(--accent-color-color))` | +| `--button-outlined-border-error-color` | `var(--button-outlined-border-error-color, var(--error-color))` | +| `--button-outlined-border-success-color` | `var(--button-outlined-border-success-color, var(--success-color))` | | `--button-text-text-color` | `var(--button-text-text-color, var(--text-primary-color))` | | `--button-text-text-color-hover` | `var(--button-text-text-color-hover, var(--text-secondary-color))` | | `--button-text-text-color-active` | `var(--button-text-text-color-active, var(--text-secondary-color))` | @@ -110,11 +123,13 @@ Only variables actually referenced in `src/components/Button/button.module.scss` | `--button-border-radius-md` | `var(--button-border-radius-md, 12px)` | | `--button-border-radius-lg` | `var(--button-border-radius-lg, 15px)` | | `--button-max-width` | `var(--button-max-width, 160px)` | +| `--button-children-z-index` | `var(--button-children-z-index, 3)` | +| `--button-children-line-height` | `var(--button-children-line-height, inherit)` | Notes: - In the `--full-radius` modifier, the border-radius is set to `var(--button-height, 999px)` (it reuses `--button-height` as the variable with a default of `999px`). -- Theme variables seen within fallbacks include `--font-family`, `--font-size`, `--line-height`, `--bg-primary-color`, `--text-primary-color`, `--text-secondary-color`, and color tokens `--primary-color`, `--secondary-color`, `--accent-color`. +- Theme variables seen within fallbacks include `--font-family`, `--font-size`, `--line-height`, `--speed-color`, `--speed-sm`, `--bg-primary-color`, `--bg-secondary-color`, `--text-primary-color`, `--text-secondary-color`, and color tokens `--primary-color`, `--secondary-color`, `--accent-color`, `--error-color`, `--success-color`. - Modifiers like `.button--primary-color` apply `--primary-color` (etc.) directly; those aren’t fallbacks but direct color assignments for that modifier. ### Theming and global configuration diff --git a/docs/Select.md b/docs/Select.md index ab07429..58ff15b 100644 --- a/docs/Select.md +++ b/docs/Select.md @@ -58,7 +58,6 @@ Supports contextual props via the UI provider: `useComponentProps("select")`. | Prop | Type | Default | | ------------------- | ------------------------ | ------- | | `center` | `boolean` | `false` | -| `fullWidth` | `boolean` | β€” | | `ellipsis` | `boolean` | `true` | | `icon` | `ReactNode` | β€” | | `placeholder` | `ReactNode` | β€” | @@ -126,6 +125,9 @@ Only variables actually referenced in `src/components/Select/select.module.scss` | `--select-trigger-padding` | `var(--select-trigger-padding, 8px 12px)` | | `--select-trigger-height` | none (define in theme) | | `--select-trigger-gap` | `var(--select-trigger-gap, 5px)` | +| `--select-speed-border-color` | `var(--select-speed-border-color, var(--speed-color))` | +| `--select-speed-box-shadow` | `var(--select-speed-box-shadow, var(--speed-color))` | +| `--select-speed-bg` | `var(--select-speed-bg, var(--speed-color))` | | `--select-placeholder-color` | `var(--select-placeholder-color, var(--placeholder-color))` | | `--select-trigger-shadow-offset-hover` | none (define in theme) | | `--select-trigger-border-width-hover` | `var(--select-trigger-border-width-hover, var(--select-trigger-border-width, 1px))` | diff --git a/package-lock.json b/package-lock.json index 906f863..b793003 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19553,42 +19553,57 @@ } }, "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-8.0.0.tgz", + "integrity": "sha512-ZOffsNrXYggvU1mDGHk54I96r26P8SyMjO5slMKSc7+IWmtB/MQKnEC2fP51imB3/pT6YK5cT5E8f+Dd9KdyOQ==", "dev": true, "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "glob": "^13.0.6", + "minimatch": "^10.2.2" }, "engines": { - "node": ">=8" + "node": "20 || >=22" + } + }, + "node_modules/test-exclude/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" } }, "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^5.0.8" }, "engines": { - "node": "*" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/thingies": { diff --git a/package.json b/package.json index a3cf9cd..b9b2b30 100644 --- a/package.json +++ b/package.json @@ -140,6 +140,7 @@ }, "overrides": { "flat-cache": "^6.1.18", - "glob": "^13.0.0" + "glob": "^13.0.0", + "test-exclude": "^8.0.0" } } diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 23b8b18..917cbff 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -41,7 +41,7 @@ const Button: ForwardRefRenderFunction = (props, }, className )} - childrenClassName={classnames(styles["button__text"], childrenClassName)} + childrenClassName={classnames(styles["button__children"], childrenClassName)} > {children} diff --git a/src/components/Button/button.module.scss b/src/components/Button/button.module.scss index a66e649..e3ee2a2 100644 --- a/src/components/Button/button.module.scss +++ b/src/components/Button/button.module.scss @@ -11,6 +11,7 @@ $root: button; padding: var(--button-padding, 0 16px); transition: color var(--button-speed-color, var(--speed-color)), + border-color var(--button-speed-border-color, var(--speed-color)), background var(--button-speed-bg, var(--speed-color)), transform var(--button-speed-transform, var(--speed-sm)); @@ -25,31 +26,31 @@ $root: button; // Variants &--contained { - color: var(--button-contained-text-color, var(--bg-primary-color)); - background: var(--button-contained-bg-color, var(--text-primary-color)); + color: var(--button-contained-text-color, var(--text-primary-color)); + background: var(--button-contained-bg-color, var(--bg-secondary-color)); &.#{$root}--primary-color { - color: #fff; + color: var(--button-contained-primary-text-color, #fff); background: var(--primary-color); } &.#{$root}--secondary-color { - color: #fff; + color: var(--button-contained-secondary-text-color, #fff); background: var(--secondary-color); } &.#{$root}--accent-color { - color: #fff; + color: var(--button-contained-accent-text-color, #fff); background: var(--accent-color); } &.#{$root}--error-color { - color: #fff; + color: var(--button-contained-error-text-color, #fff); background: var(--error-color); } &.#{$root}--success-color { - color: #fff; + color: var(--button-contained-success-text-color, #fff); background: var(--success-color); } } @@ -160,14 +161,14 @@ $root: button; border-radius: var(--button-height, 999px); } - &__text { + &__children { position: relative; - z-index: 3; + z-index: var(--button-children-z-index, 3); white-space: nowrap; text-overflow: ellipsis; overflow: hidden; max-width: var(--button-max-width, 160px); - line-height: initial; + line-height: var(--button-children-line-height, inherit); transition: color var(--button-speed-color, var(--speed-color)); } } diff --git a/src/components/Select/SelectTrigger.tsx b/src/components/Select/SelectTrigger.tsx index 94c36d5..9953ac7 100644 --- a/src/components/Select/SelectTrigger.tsx +++ b/src/components/Select/SelectTrigger.tsx @@ -17,7 +17,6 @@ import styles from "./select.module.scss"; export interface SelectTriggerProps extends SelectTriggerRadixProps { center?: boolean; - fullWidth?: boolean; ellipsis?: boolean; icon?: React.ReactNode; placeholder?: React.ReactNode; diff --git a/src/components/Select/select.module.scss b/src/components/Select/select.module.scss index 56f25dd..29b0e18 100644 --- a/src/components/Select/select.module.scss +++ b/src/components/Select/select.module.scss @@ -24,7 +24,10 @@ $root: select; padding: var(--select-trigger-padding, 8px 12px); height: var(--select-trigger-height); gap: var(--select-trigger-gap, 5px); - + transition: + border-color var(--select-speed-border-color, var(--speed-color)), + box-shadow var(--select-speed-box-shadow, var(--speed-color)), + background var(--select-speed-bg, var(--speed-color)); &--center { justify-content: center; } diff --git a/src/plugin/index.ts b/src/plugin/index.ts index 2232472..4b5480a 100644 --- a/src/plugin/index.ts +++ b/src/plugin/index.ts @@ -22,13 +22,13 @@ export interface PluginOptions { /** * Name of the configuration file. - * @default "config.ui" + * @default "ui.config" */ configName?: string; /** * Name of the style file. - * @default "style.ui" + * @default "ui.style" */ styleName?: string; @@ -47,7 +47,7 @@ export interface PluginOptions { /** * Configuration for splitting chunks. * Can be a boolean to enable/disable or a callback to customize chunk names. - * @default true + * @default false */ splitChunks?: boolean | ((name: string) => string | undefined); } diff --git a/tests/release-it.test.cjs b/tests/release-it.test.cjs new file mode 100644 index 0000000..2bb08da --- /dev/null +++ b/tests/release-it.test.cjs @@ -0,0 +1,45 @@ +const {whatBump} = require("../.release-it.cjs"); + +describe("release-it version policy", () => { + describe("breaking changes", () => { + test.each([ + ["parser breaking field", {type: "feat", breaking: "!"}], + ["type suffix", {type: "feat!"}], + ["header suffix", {type: "feat", header: "feat(ui)!: remove legacy API"}], + ["BREAKING CHANGE note", {type: "fix", notes: [{title: "BREAKING CHANGE", text: "new contract"}]}], + ["BREAKING-CHANGE footer", {type: "fix", footer: "BREAKING-CHANGE: new contract"}], + ])("treats %s as a pre-1.0 minor bump", (_label, commit) => { + expect(whatBump([commit], "0.11.0")).toEqual({level: 1}); + }); + + test("becomes a major bump after 1.0", () => { + expect( + whatBump([{type: "fix", notes: [{title: "BREAKING CHANGE", text: "new contract"}]}], "1.4.2") + ).toEqual({level: 0}); + }); + + test("takes precedence over lower-level changes after 1.0", () => { + expect(whatBump([{type: "fix"}, {type: "feat"}, {type: "refactor", breaking: true}], "2.0.0")).toEqual({ + level: 0, + }); + }); + }); + + test("uses a minor bump for feat", () => { + const type = "feat"; + + expect(whatBump([{type}], "0.11.0")).toEqual({level: 1}); + }); + + test.each(["fix", "perf", "refactor", "ci"])("uses a patch bump for %s", type => { + expect(whatBump([{type}], "0.11.0")).toEqual({level: 2}); + }); + + test("uses the highest non-breaking bump", () => { + expect(whatBump([{type: "fix"}, {type: "feat"}], "0.11.0")).toEqual({level: 1}); + }); + + test.each(["docs", "test", "chore", "build"])("does not release for %s alone", type => { + expect(whatBump([{type}], "0.11.0")).toBeNull(); + }); +});