diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index dadcf6e3..54231820 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -39,6 +39,7 @@ on: permissions: contents: write + pull-requests: read jobs: release: @@ -164,7 +165,29 @@ jobs: needs: [release] steps: - - name: Report that nothing was published + - name: Verify an intentional no-release merge + env: + GH_TOKEN: ${{ github.token }} run: | - echo "::error::Nothing was published and no release was cut (reason: ${{ needs.release.outputs.reason }}). For 'no-label', add exactly one of major, minor or patch to the merged pull request and re-run this workflow - see verify-semver-label, which is meant to catch this before the merge." + reason='${{ needs.release.outputs.reason }}' + if [ "$reason" = "error" ]; then + echo "::error::The release action failed; no-release cannot suppress a release error." + exit 1 + fi + + pulls=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/pulls") + merged_count=$(printf '%s' "$pulls" | jq --arg sha "$GITHUB_SHA" '[.[] | select(.merge_commit_sha == $sha)] | length') + if [ "$merged_count" -ne 1 ]; then + echo "::error::Expected exactly one pull request whose merge commit is $GITHUB_SHA; found $merged_count." + exit 1 + fi + no_release=$(printf '%s' "$pulls" | jq -r --arg sha "$GITHUB_SHA" \ + '[.[] | select(.merge_commit_sha == $sha) | .labels[].name] | any(. == "no-release")') + + if [ "$no_release" = "true" ]; then + echo "The merged pull request explicitly selected no-release; publishing nothing is the intended result." + exit 0 + fi + + echo "::error::Nothing was published and no release was cut (reason: ${{ needs.release.outputs.reason }}). Add exactly one release-intent label before merge; use no-release when publishing nothing is intentional." exit 1 diff --git a/.github/workflows/verify-semver-label.yml b/.github/workflows/verify-semver-label.yml index cb60751f..c0ec3280 100644 --- a/.github/workflows/verify-semver-label.yml +++ b/.github/workflows/verify-semver-label.yml @@ -1,12 +1,8 @@ name: Verify Semver Label -# A merged pull request with no major/minor/patch label produces a Publish run that reports success while -# skipping every publish step, because the release action resolves should-publish to false. That reads as a -# release having happened when nothing was published. Requiring the label here turns a silent non-release into -# a visible failure before the merge, where it costs nothing to fix. -# -# It also closes a race the publish workflow cannot: a label added moments after the merge may land too late -# for the release to pick it up. Demanding the label before the merge means there is nothing to race. +# Every pull request declares one release intent. major/minor/patch authorizes a package release when the +# publish workflow's path filters also match; no-release explicitly records that the change should publish +# nothing. Requiring exactly one intent prevents both accidental releases and ambiguous silent skips. # # Triggered on labeled/unlabeled as well as the usual events, so adding the label re-runs the check rather than # leaving a red cross behind that only a push would clear. @@ -16,7 +12,7 @@ concurrency: on: pull_request: - types: [opened, reopened, synchronize, labeled, unlabeled] + types: [opened, reopened, synchronize, labeled, unlabeled, edited] # Scoped to the same branch Publish releases from. A pull request stacked onto another one's branch cannot # cut a release, so demanding a version label of it would be asking which version a merge that publishes # nothing should carry. @@ -31,21 +27,21 @@ jobs: runs-on: ubuntu-latest steps: - - name: Require exactly one semantic version label + - name: Require exactly one release-intent label env: LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }} run: | - count=$(printf '%s' "$LABELS" | jq '[.[] | select(. == "major" or . == "minor" or . == "patch")] | length') + count=$(printf '%s' "$LABELS" | jq '[.[] | select(. == "major" or . == "minor" or . == "patch" or . == "no-release")] | length') if [ "$count" -eq 1 ]; then - echo "Found one semantic version label." + echo "Found one release-intent label." exit 0 fi if [ "$count" -eq 0 ]; then - echo "::error::This pull request has no semantic version label. Add exactly one of major, minor or patch. Without one, merging produces a Publish run that succeeds while skipping every publish step, so no release is cut and nothing is published." + echo "::error::This pull request has no release-intent label. Add exactly one of major, minor, patch or no-release." else - echo "::error::This pull request carries $count semantic version labels. Exactly one of major, minor or patch is required, since the release version cannot be derived from more than one." + echo "::error::This pull request carries $count release-intent labels. Add exactly one of major, minor, patch or no-release." fi exit 1 diff --git a/Codemods/README.md b/Codemods/README.md index 74db1966..f15f2e49 100644 --- a/Codemods/README.md +++ b/Codemods/README.md @@ -1,8 +1,6 @@ # @cratis/components-codemods -Published migration codemods for moving from Components 3 root namespaces to Components 4 explicit subpath imports. Components 4 keeps only package-wide provider setup at the root; every component is imported from its explicit subpath (`@cratis/components/Canvas`, for example). See the published -[`no-root-barrel-import` ESLint rule](https://www.npmjs.com/package/@cratis/eslint-plugin-components#no-root-barrel-import) -for the lint-time guard that enforces this once a consumer has migrated. +Migration codemods in the Components 4 candidate move Components 3 root namespaces to Components 4 explicit subpath imports. Components 4 keeps only package-wide provider setup at the root; every component is imported from its explicit subpath (`@cratis/components/Canvas`, for example). The companion `@cratis/eslint-plugin-components` package's `no-root-barrel-import` rule enforces this once a consumer has migrated. ## `remove-root-namespace-imports` @@ -80,8 +78,10 @@ consumers are left exactly as they are. ### Use -The published CLI requires Node.js 20 or newer and brings its own TypeScript parser; it does -not depend on the consumer application's TypeScript version. +The packaged CLI requires Node.js 20 or newer and brings its own TypeScript parser; it does +not depend on the consumer application's TypeScript version. Use the `npx` commands only with +an exact published package version that contains this tool; contributors can run the repository +source directly. ```sh # Preview what would change, without writing anything: diff --git a/Documentation/getting-started.mdx b/Documentation/getting-started.mdx index 33a5d8cb..a7fc8916 100644 --- a/Documentation/getting-started.mdx +++ b/Documentation/getting-started.mdx @@ -7,7 +7,7 @@ sidebar: import { Steps, Aside } from '@astrojs/starlight/components'; -You've built an Arc backend—a `RegisterAuthor` command and an `AllAuthors` query—and `dotnet build` generated typed proxies for both. Components turns those proxies into accessible forms, dialogs, and data views without duplicating command state, validation, or query lifecycle code. +You've built an Arc backend—a `RegisterAuthor` command and an `AllAuthors` query—and `dotnet build` generated typed proxies for both. Components connects those proxies to typed forms, dialogs, and data views with documented command, validation, and query-lifecycle behavior. ## Prerequisites @@ -24,9 +24,9 @@ You've built an Arc backend—a `RegisterAuthor` command and an `AllAuthors` que npm install @cratis/components ``` - React Aria and the internationalized date implementation are internal dependencies. You do not install a UI kit, theme runtime, icon package, or commercial license for Components. + React Aria and the internationalized date implementation are internal dependencies. The current package manifest does not declare a separate UI kit, theme runtime, or icon package as a dependency or peer. - The remaining peers—React, Arc, Fundamentals, `reflect-metadata`, and `tsyringe`—already come with an Arc frontend. Arc 20, 21, and 22 are supported. + The package declares React, Arc, Fundamentals, `reflect-metadata`, and `tsyringe` peer ranges. Its Arc range is `>=20.3.1 <23`; verify the exact manifest and application profile before installation. `pixi.js@^8.20.0` is an additional **optional** peer, needed only if you use `Canvas` or `PivotViewer`. Every other component needs nothing beyond the peers above; install Pixi later, when you reach a spatial workspace or card-grid screen. See [Choosing a component](/components/choosing-a-component/#spatial-workspaces). @@ -50,7 +50,7 @@ You've built an Arc backend—a `RegisterAuthor` command and an `AllAuthors` que 3. **Mount the provider** around your application: ```tsx title="App.tsx" - import { CratisComponentsProvider } from '@cratis/components/Common'; + import { CratisComponentsProvider } from '@cratis/components'; export const App = () => ( @@ -140,7 +140,7 @@ Do not target React Aria class names or internal DOM structure. See [Styling](/c ## Recap -You installed one UI package, imported Cratis-owned styles, and mounted a locale/toast provider. Components owns the public UI contract while Arc supplies command and query behavior and React Aria supplies low-level accessible interactions. +You installed one UI package, imported Components-owned styles, and mounted a locale/toast provider. Components owns the public React contract, Arc supplies command and query behavior, and React Aria supplies selected low-level interaction primitives internally. ## Where to go next diff --git a/Documentation/index.mdx b/Documentation/index.mdx index 7d5effe0..e948852e 100644 --- a/Documentation/index.mdx +++ b/Documentation/index.mdx @@ -1,93 +1,117 @@ --- title: Components -description: The React component library for Cratis — command dialogs, forms, and data tables that consume Arc's generated proxies. +description: React components aligned with Arc application patterns. --- -import { CardGrid } from '@astrojs/starlight/components'; +import { Card, CardGrid, Steps } from '@astrojs/starlight/components'; import SimpleCard from '@components/SimpleCard.astro'; import TopicHero from '@components/TopicHero.astro'; - Command dialogs, forms, and data tables that consume [Arc's](/arc/) generated proxies. - Cratis-owned, fully typed, accessible, and styled the way you choose. [Get started - →](/components/getting-started/) · [Why Components? →](/components/why-components/) + Components is a React component library aligned with Arc application patterns. + The current package owns its public React markup, TypeScript contracts, + semantic tokens, stable parts, and component behavior. ## Start here - - Install the package, mount the provider, and render your first proxy-driven - screen. - - - What the library adds around generated Arc proxies and accessible interaction - behavior. - - - Use the baseline theme or map a product design system directly onto Cratis tokens - and parts. - + + Install the package, import its structural styles, and mount the provider. + + + Start from the screen job rather than a raw component inventory. + + + Distinguish Arc-generated contracts from the React compositions that consume them. + -## Recipes +## Minimal setup + + +1. Install the package. + + ```bash + npm install @cratis/components + ``` + +2. Import semantic tokens and component structure. The baseline theme is + optional. + + ```tsx + import '@cratis/components/tokens'; + import '@cratis/components/styles'; + import '@cratis/components/theme'; // optional baseline appearance + ``` + +3. Mount the provider. + + ```tsx + import { CratisComponentsProvider } from '@cratis/components'; + + export const App = () => ( + + + + ); + ``` + + +The current package manifest defines the exact React, Arc, Fundamentals, and +optional Pixi peer ranges. Verify those ranges for the package version selected. + +## Relationship to Arc + +Components consumes generated command and query contracts and React contexts +from Arc packages. Applications may use Arc without Components. + +Components does not by itself establish design-system completeness, +accessibility conformance, browser coverage, or compatibility with every +Arc/React/package-version combination. + +## Component areas - - Collect input and execute a command with `CommandDialog` and the `CommandForm` - fields. - - - Render a query or observable query with `DataPage` and the data-table wrappers. - - - Gather information across named stages with `StepperCommandDialog`. - - - A full screen: list rows, add and edit through dialogs, and react to selection. - + + Typed fields, forms, dialogs, and multi-step command flows. + + + Query-backed and local-array tables, list pages, filters, and detail surfaces. + + + Dialogs, notifications, dropdowns, display primitives, page chrome, and toolbars. + + + JSON content, JSON Schema, navigation, canvas, pivot, and time-oriented views. + + + Semantic tokens, component styles, an optional baseline theme, and stable parts. + -## Key components +:::caution[Evaluate the exact application profile] +Package existence, examples, Storybook output, and passing checks do not +establish maturity, accessibility conformance, browser coverage, support, +security, or production suitability. Direct third-party UI dependencies retained +by an application keep their own package, provider, styling, and license +boundaries. +::: + +## Continue - - Instantiates, validates, and executes a generated command, with the footer handled - for you. - - - A resizable page that lists query data with toolbar actions and detail panels. - - - Typed input fields bound to command properties — text, number, dropdown, date, and - more. - - - Data-collection dialogs that return values without executing a command. - - - A pan/zoom workspace with measured items, controls, minimap, notes, regions, and chat shapes. - + + Package setup, migration guidance, contribution paths, and current limits. + + + Published package metadata and versions. + + + The CQRS framework whose application patterns Components aligns with. + - -Components renders [Arc](/arc/) command and query proxies. Those queries can come from Chronicle read models in an event-sourced application or from any Arc query source — Chronicle is optional. See [Why developers choose Cratis](/why-cratis/) for the full stack. diff --git a/Documentation/migration.md b/Documentation/migration.md index 8060af51..c4378ddb 100644 --- a/Documentation/migration.md +++ b/Documentation/migration.md @@ -3,16 +3,12 @@ title: Migrate from Components 3 to 4 description: Move from the PrimeReact-backed release to the renderer-independent React Aria foundation. --- -Components 4 replaces the mandatory PrimeReact 11 foundation with Cratis-owned markup, styling contracts, and public types. React Aria supplies accessible interaction behavior internally. Applications no longer install, configure, license, theme, or type against PrimeReact to use Components. +Components 4 replaces the PrimeReact-backed Components 3 foundation with Components-owned markup, styling contracts, and public types. React Aria supplies selected interaction primitives internally. The current Components 4 manifest does not declare PrimeReact, PrimeIcons, PrimeUI, or PrimeUI themes as dependencies or peers; applications retaining direct imports keep their own package and license boundaries. -This is intentionally a major release. Component behavior remains familiar, but rendered markup, styling parts, provider configuration, date entry, and some deprecated props change. +This is a major-version migration. Rendered markup, styling parts, provider configuration, date entry, root imports, and some deprecated props change. :::note -Components 3 remains the compatibility line for an application that cannot migrate yet. A separate PrimeReact compatibility package will not be published unless PrimeTek confirms the applicable OEM and redistribution terms in writing. - -**What staying on Components 3 means.** Components 3 keeps PrimeReact 11 as a peer dependency, and PrimeReact 11 verifies a PrimeUI license key when its provider mounts — on every styling path, including unstyled and the MIT Cratis baseline theme, in development and production. Without a valid key the application shows a fixed _"Invalid PrimeUI License"_ banner. The free Community key is eligibility-limited and must be renewed annually; an expired Community key has a 30-day grace period before the banner returns. See [the Components 2 to 3 guide's licensing section](migration-from-2.md#licensing) for the full terms. - -Components 3 receives security and critical defect fixes as the migration compatibility line; it receives no new features or foundation work. Plan the move to Components 4 rather than treating Components 3 as a steady state. +An application that has not migrated remains on its exact Components 3 package profile, including the third-party dependencies declared by that version. Components 4 does not currently publish a Prime compatibility package. Review the exact package manifests and third-party terms for the version the application keeps. This guide makes no support-window, security-fix, maintenance, or future-package commitment for either major. ::: ## Update dependencies @@ -32,7 +28,7 @@ Keep a Prime package only when your application still imports it directly. Migra Applications using Canvas or PivotViewer must install `pixi.js@^8.20.0`, now an optional peer rather than a nested Components dependency. Align any existing direct Pixi dependency to the same compatible resolution so public `PIXI.Container` and pointer-event types come from one package instance. Applications using only non-Pixi subpaths do not need it. -The supported Arc peer range remains `>=20.3.1 <23`. +The package declares an Arc peer range of `>=20.3.1 <23`. ## Import from explicit subpaths @@ -88,7 +84,7 @@ This is an intentional Components 4 breaking change. The package root now expose `@cratis/components/CommandForm/fields` is the same module as `@cratis/components/CommandForm` — either subpath resolves identically, so the `CommandForm` row's migration applies to both. -Run the shipped AST-based codemod in preview mode first, then apply it: +Run the migration codemod in preview mode first, then apply it: ```bash npx --package @cratis/components-codemods \ @@ -213,7 +209,7 @@ This removes the old product-token → Prime preset → Prime variable → Crati ## Removed accidental package exports -An audit of the published `exports` map ([#173](https://github.com/Cratis/Components/issues/173)) found implementation-only symbols that were unintentionally reachable from a public subpath — each was exported only because the owning module's barrel used a blanket `export *`, not because it was a supported contract. Components 4 stops re-exporting them from their public barrel; the underlying files keep the symbol for their own internal cross-file use, so this is a package-export change only, not a behavior change. +An audit of the package `exports` map ([#173](https://github.com/Cratis/Components/issues/173)) found implementation-only symbols that were unintentionally reachable from a public subpath — each was exported only because the owning module's barrel used a blanket `export *`, not because it was a supported contract. Components 4 stops re-exporting them from their public barrel; the underlying files keep the symbol for their own internal cross-file use, so this is a package-export change only, not a behavior change. | Removed export | Subpath(s) | Migration | | ------------------------------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -226,7 +222,7 @@ An audit of the published `exports` map ([#173](https://github.com/Cratis/Compon | `DEFAULT_EMOJIS`, `QUICK_ROW_SIZE` | `@cratis/components/Canvas` | Private `recentEmojis`/`rememberEmoji` constants. Not part of the public API. | | `buildFilterValues`, `buildRangeValues`, `RenderedHistogramBucket` | `@cratis/components/Filter` | Private `useFilterState`/`RangeHistogramFilter` helpers. Not part of the public API. | -None of these had a documented contract, and none is required by any other public API in this package. An application that imported one of these directly has no supported replacement to migrate to — inline the equivalent logic, or open an issue describing the use case if the behavior should become a supported public contract. +None of these had a documented contract, and none is required by any other public API in this package. An application that imported one of these directly has no documented replacement to migrate to — inline the equivalent logic, or open an issue describing the use case if the behavior should become a supported public contract. The surfaces this audit confirmed as intentional and kept public — `ToastRecord`, `getToastSnapshot`, `subscribeToToasts`, `ToastDispatch`, `EmojiMemory`, `ChatAuthorKind`, `DEFAULT_TYPE_FORMATS`, `NavigationItem`, `Json`, and `TimeMachine`'s `Properties` — are unchanged and now carry TSDoc explaining their contract and, where relevant, their extension-point role. @@ -531,7 +527,7 @@ Pass the parts to either query-backed table: - `id` identifies the focus group rather than a native text input. - The accessible calendar trigger is shown by default; set `showIcon={false}` only for segment-entry-only experiences. - `todayLabel` and `clearLabel` override the provider messages for one picker. -- `showTime` and `hourFormat` remain supported. +- `showTime` and `hourFormat` remain in the current API. ## Update Dropdown styling and semantics @@ -657,7 +653,7 @@ Complete PrimeIcons class strings remain usable where a component accepts the pu 6. Exercise dialogs, filtered tables, dates, dropdowns, toasts, and steppers with keyboard-only navigation. 7. Verify light, dark, forced-colors, reduced-motion, and responsive layouts. 8. Run TypeScript, specs, Storybook, and the production build. -9. Import components from their explicit subpath rather than the removed root namespace; apply the mapping table under [Import from explicit subpaths](#import-from-explicit-subpaths), or run the shipped codemod. +9. Import components from their explicit subpath rather than the removed root namespace; apply the mapping table under [Import from explicit subpaths](#import-from-explicit-subpaths), or run the migration codemod. A TypeScript 6 application using `skipLibCheck: false` may see bounded upstream diagnostics from Pixi's `@webgpu/types` collision with TypeScript's built-in WebGPU declarations, from `@cratis/arc.react`'s published global JSX declarations, or under NodeNext from extensionless declaration imports in the current Arc and Fundamentals packages. Components validates every packed subpath without suppressing these diagnostics; exact versions, codes, affected subpaths, and removal conditions are documented under [Strict public-type validation](ui-foundation.md#strict-public-type-validation) and tracked in [#176](https://github.com/Cratis/Components/issues/176). diff --git a/Documentation/ui-foundation.md b/Documentation/ui-foundation.md index 87814a5a..c8b42693 100644 --- a/Documentation/ui-foundation.md +++ b/Documentation/ui-foundation.md @@ -1,11 +1,11 @@ --- title: UI foundation -description: Why Components owns its public design system and uses React Aria for accessible behavior. +description: How Components owns its public React contracts and delegates selected interaction primitives. sidebar: order: 2 --- -Components 4 gives Cratis applications a stable UI API without exposing a mandatory rendering kit. The package owns its markup, TypeScript types, tokens, stable parts, and product-level behavior. React Aria supplies complex accessible interaction behavior internally. +Components 4 owns its public React markup, TypeScript types, tokens, documented parts, and component behavior without exposing its internal interaction library as a consumer contract. React Aria supplies selected focus, keyboard, overlay, collection, and date interaction primitives internally. These implementation facts do not establish accessibility conformance for every component or application. ## Shipped architecture @@ -20,7 +20,7 @@ graph TD Consumers import `@cratis/components/*`. React Aria does not appear in public prop types, declarations, or styling contracts. Arc command, query, and dialog bindings remain owned by `@cratis/arc.react`; Components builds visual behavior around them. -“Renderer-independent” here means that React applications depend on Cratis-owned contracts rather than one internal React renderer. `@cratis/components` is still a React package. A future Vue, Svelte, or other frontend should use Arc's transport/client contracts and framework-native bindings; genuinely cross-framework behavior belongs in Arc only after a second implementation proves that seam. +“Renderer-independent” here means that React applications depend on Components-owned public contracts rather than the DOM or types of one internal interaction library. `@cratis/components` remains a React package. Arc's generated transport/client contracts remain a separate boundary from Components' React composition. ## Consumer contract @@ -50,17 +50,17 @@ import { Canvas, CanvasItem } from '@cratis/components/Canvas'; `@cratis/components` intentionally exports only `CratisComponentsProvider`, `useCratisComponentsConfig`, `cratisDefaults`, `mergeCratisComponentsConfig`, and their config/props/message types — the setup every application needs once, regardless of which components it uses. Every component family, in every [capability profile](#capability-profiles), is reached through its own subpath and never through the root. -Components 4 removes the Components 3 root namespace bridge. Imports such as `import { Canvas } from '@cratis/components'` no longer resolve; use `@cratis/components/Canvas` instead. [Migrate from Components 3 to 4](migration.md) carries the complete namespace-to-subpath mapping and the public codemod command. One compatibility nuance is encoded there and in the tooling: the historical root `CommandStepper` namespace represented the entire `CommandDialog` module, so it migrates to `@cratis/components/CommandDialog`; the narrower `@cratis/components/CommandStepper` subpath still exports only `CommandStepper`. +Components 4 removes the Components 3 component-family namespaces from the root. Imports such as `import { Canvas } from '@cratis/components'` no longer resolve; use `@cratis/components/Canvas` instead. [Migrate from Components 3 to 4](migration.md) carries the current namespace-to-subpath mapping, codemod command, and stop conditions. The `CommandStepper` mapping is intentionally special: the historical namespace represented the full `CommandDialog` module, so it migrates to `@cratis/components/CommandDialog`; the narrower `@cratis/components/CommandStepper` subpath exports only the standalone component. ## Capability profiles -Components groups its subpaths into three capability profiles — a documentation and adoption grouping, not a support tier: +Components groups its subpaths into three capability profiles for documentation, dependencies, and adoption. The profiles do not assign maturity, accessibility, support, or quality tiers: - **Foundation** — the components most applications reach for immediately: `Common`, `CommandDialog` (and its `CommandStepper` alias), `CommandForm` (and `CommandForm/fields`), `DataPage`, `DataTables`, `Dialogs`, `Display`, `Dropdown`, `Filter`, `Notifications`, and `types`. Forms, dialogs, tables, and notifications for an ordinary Arc-backed CRUD screen. - **Advanced React** — specialized, still Pixi-free React surfaces used by fewer applications, or by fewer screens within an application: `ObjectContentEditor`, `ObjectNavigationalBar`, `SchemaEditor`, `TimeMachine`, and `Toolbar`. JSON Schema authoring, object/schema navigation, version scrubbing, and canvas-style tool palettes. - **Spatial** — pan/zoom and large-dataset visualization surfaces backed by Pixi: `Canvas` and `PivotViewer`. These install the optional `pixi.js` peer; see [Optional Pixi, clean no-Pixi core](#optional-pixi-clean-no-pixi-core). -**Equal support, not weaker semver.** All three profiles, and the setup-only root, ship from the same package at the same version, pass the same [release gates](#release-gates) — build, specs, Storybook, package-export verification, SSR, accessibility, and strict public-type validation — and follow the same single semver line. A breaking change to `Toolbar` bumps the same major version as a breaking change to `DataTableForQuery`. "Advanced React" and "Spatial" describe what a component is _for_ and what it costs to adopt (peer install, bundle shape, typical audience) — never how carefully it is built, tested, or versioned. +All three profiles and the setup-only root are exported from the same package version. “Advanced React” and “Spatial” describe purpose and additional dependency shape, not how carefully a component is built, tested, supported, or versioned. Review the exact package manifest, subpath, component documentation, and application evidence for the profile you use. ## Capability matrix @@ -103,7 +103,7 @@ A future split — for example, a separate `@cratis/components/styles/spatial` a - A capability profile needs an independently versioned or independently loaded stylesheet — for example, a CDN-hosted or lazily loaded Spatial bundle separate from the application shell. - Splitting no longer risks the two-file drift the single manifest exists to prevent, or the build gate that enforces it is extended to cover multiple manifests without weakening it. -Until then, one manifest is simpler to keep correct than several kept in sync, and it matches the "equal support" statement in [Capability profiles](#capability-profiles): no profile's styling is a second-class, separately loaded concern. +For the current package, one manifest keeps component and stylesheet reachability under one repository gate rather than introducing multiple manifests that can drift. ## Package split criteria @@ -111,7 +111,7 @@ Until then, one manifest is simpler to keep correct than several kept in sync, a - **Peer isolation stops being enough.** The optional `pixi.js` peer plus subpath exports already means a Foundation-only application installs no Pixi code and imports no Pixi module. A split would only remove marginal package-manager or type-resolution overhead beyond what the optional peer already removes — that overhead would need to be measured and real, not assumed. - **A capability profile needs an independent release cadence.** For example, a Pixi major upgrade that must ship for `Canvas`/`PivotViewer` without forcing a coordinated release of every Foundation and Advanced React component, or vice versa. Today all three profiles share one version and one release process by design — see [Capability profiles](#capability-profiles). -- **A second framework binding needs to reuse non-visual logic without pulling in React-specific Spatial code.** The [table architecture](#table-architecture) section already anticipates this for an Arc React query/table binding; the same reasoning would apply to any Foundation/Advanced React logic a future Vue or Svelte binding wants to share, while Spatial's Pixi/React composition would not be reusable as-is regardless of packaging. +- **A separately owned non-visual contract is proven outside Components' React composition.** The [table architecture](#table-architecture) section keeps Arc query/transport ownership separate from visual table state today. - **The aggregate CSS manifest is split first.** See [Aggregate CSS today, future split criteria](#aggregate-css-today-future-split-criteria) — a package split typically follows the same boundary as its stylesheets, so splitting packages before an already-justified CSS split would just recreate the drift problem the manifest exists to prevent, across package boundaries instead of within one. None of these conditions is met today. A single package with subpath exports, an optional Pixi peer, and one aggregate stylesheet already delivers tree-shakeable code, no forced Pixi install, one `--cratis-*` token source, and one release/versioning/CI surface — the practical benefits a split would chase — without a multi-package version matrix to keep compatible across three profiles that already share every build, spec, and release gate. @@ -128,37 +128,27 @@ The React Aria Components Toast API remains unstable, so Components 4 ships its Components 4 uses semantic React HTML and Cratis-owned table state. `DataTableCore` is a rendered React component, not a headless or framework-neutral table engine. Arc remains authoritative for server paging. Client filtering and sorting operate only on the loaded page. Complete-result filtering and sorting require consumer-defined query arguments and server query logic that applies them before paging; Components does not automatically forward table state to the server. -The reusable cross-framework seam today is Arc's generated query/transport contract and explicit paging/query arguments—not Components' React table state. [Issue #109](https://github.com/Cratis/Components/issues/109) tracks a possible headless Arc React query/table binding. It should be designed in Arc React, separately from visual policy, and only after real consumer implementations establish the required sorting, filtering, selection, and observable-query state. A future Vue or Svelte binding would build framework-native state over the same Arc transport contract rather than reuse `DataTableCore`. +The reusable product boundary today is Arc's generated query/transport contract and explicit paging/query arguments—not Components' React table state. Components does not currently export `DataTableCore` as a framework-neutral table engine or forward loaded-page table state to the server automatically. -[TanStack Table](https://tanstack.com/table/latest/docs/overview) was evaluated but is not a Components 4 dependency. It remains a possible future implementation tool if advanced grouping, pinning, faceting, or sizing creates enough state complexity to justify it. Adopting it would not change the Cratis public contract. +## Prime dependency boundary -## Why PrimeReact is no longer the default - -PrimeReact 11 has a capable layered architecture, but PrimeUI's consumer contract is unsuitable as an invisible mandatory dependency of a general Cratis framework. - -Two facts about that contract are directly verifiable. First, PrimeReact 11 enforces licensing at runtime: `PrimeReactProvider` verifies a PrimeUI license key when it mounts, with no condition on unstyled rendering, on the applied theme, or on the build environment — verified against the published `@primereact/core` 11.1.0 artifact. Without a valid key the application logs a warning and shows a fixed _"Invalid PrimeUI License"_ banner, in development and production. Verification is offline — a signature check against an embedded public key, with no telemetry. Second, the upstream `primefaces/primereact` repository is archived; PrimeReact development continues under the commercial PrimeUI model, and only the pre-11 MIT versions remain MIT. A mandatory dependency with runtime license enforcement and no open-source development line cannot sit invisibly underneath every Cratis application. - -The [PrimeUI Community License](https://primeui.dev/licenses/community) says developers building on an internal wrapper or design system still need seats. Eligibility excludes organizations by revenue, team size, funding, or public-sector status. The [OEM guidance](https://primeui.dev/licenses/oem) identifies frameworks and SDKs used for third-party development as potential OEM uses while not clarifying peer-only open-source wrappers. - -No `@cratis/components.primereact` package is published. Such a package is only a conditional future option and requires written PrimeTek confirmation first. Consumers that need the old implementation remain on the Components 3 release line while migrating. - -This documentation summarizes public terms for architectural transparency; it is not legal advice. Consumers must consult the current authoritative license terms and their own counsel. +The Components 4 package manifest does not declare PrimeReact, PrimeIcons, PrimeUI, or PrimeUI theme packages as dependencies or peers. Applications that still import those packages directly retain their own package, provider, styling, version, and license boundaries. Review the exact third-party package terms for the version an application keeps; this page makes no licensing conclusion for that application. ## Why Components does not implement every interaction itself -Owning the API does not mean independently rebuilding dialog focus traps, composite keyboard navigation, international calendars, and collection selection. Components delegates those low-level behaviors to an open specialized foundation and verifies the composed result. +Owning the API does not mean independently rebuilding dialog focus traps, composite keyboard navigation, international calendars, and collection selection. Components delegates selected low-level behaviors to an open specialized foundation and exercises the resulting component behavior through owning repository specs and diagnostics. Simple controls use semantic native HTML when that is more robust than introducing an abstraction. ## Release sequence -The transition was deliberately split: +The transition is split by current artifact behavior: -1. Components 3 received a source-compatible stabilization release with accessibility, localization, filtering, notification, and paging fixes while retaining explicit PrimeUI requirements. -2. Components 4 changes the default foundation, removes Prime runtime/declaration references, and introduces Cratis-owned provider and styling contracts. -3. Components 3 remains the temporary compatibility line for applications that cannot migrate atomically, receiving security and critical defect fixes but no new features or foundation work. +1. Components 3 retains its documented Prime-backed package and migration starting point. +2. Components 4 changes the default foundation, removes Prime runtime/declaration references from its package, and introduces Components-owned provider and styling contracts. +3. The migration guide records the current breaking changes and mechanical import path. It does not establish a support window or future maintenance commitment for either major. -The stabilization specs are the behavior parity contract for Components 4. +Repository specs compare bounded behaviors needed by the current migration; they do not establish universal behavior parity or accessibility conformance. ## Strict public-type validation @@ -176,29 +166,28 @@ The current exceptions are: `CanvasContext`, `renderItem`, and pointer callbacks intentionally expose real Pixi objects so consumers can build arbitrary Pixi content. Replacing those types with reduced Cratis facades would either duplicate Pixi's API or force consumers to cast back to it. The bounded WebGPU declaration exception is preferable to weakening this intentional extensibility contract. `pixi.js` is therefore an optional peer: Canvas/PivotViewer consumers install one compatible `^8.20.0` resolution, preventing nested nominally-incompatible Pixi instances while non-Pixi subpaths impose no installation requirement. PivotViewer does not expose Pixi types publicly and needs no equivalent declaration exception. -## Tracked follow-up work +## Current limitations and work records -Components 4 deliberately does not pretend every adjacent problem is solved by this renderer change: +Components 4 does not treat adjacent gaps as part of the current package contract: -- [#109](https://github.com/Cratis/Components/issues/109) tracks a future Arc React query/table state binding, to be extracted only after another renderer proves the contract. -- [#178](https://github.com/Cratis/Components/issues/178) tracks explicit complete-result filtering and sorting through server query arguments before paging. The deprecated `clientFiltering` compatibility prop is not that solution. -- [#174](https://github.com/Cratis/Components/issues/174) tracks localization beyond the pre-stable provider-message tranche, including generated labels and plural/relative text. -- [#175](https://github.com/Cratis/Components/issues/175) tracks a locale-aware number input so products can remove specialized Prime inputs without losing number UX. -- [#179](https://github.com/Cratis/Components/issues/179) tracks the exact-artifact downstream RC runtime and visual pilots required before stable release. +- Complete-result filtering and sorting remain server-query concerns before paging; loaded-page controls do not supply that behavior. +- Some generated labels and plural/relative text remain outside the current provider-message subset. +- The current package has no Components-owned locale-aware number input. +- Exact-artifact downstream runtime and visual evidence remains part of the major release review. -These are follow-up contracts, not undocumented work required to use the Components 4 foundation. +Repository issues may track these gaps, but an open issue is not a public roadmap or delivery commitment. ## Release gates -Components 4 is accepted only when: +The Components 4 major candidate uses these repository release checks: - Emitted JavaScript and declarations contain no Prime imports or type references. -- A real npm packed consumer installs and runs with Pixi absent; strict pnpm and Yarn PnP consumers pass with Pixi both absent and present, and the present topology proves Components and the consumer resolve one Pixi instance. +- Real npm, strict pnpm, and Yarn PnP packed consumers pass with Pixi both absent and present; present topologies prove Components and the consumer resolve one Pixi instance. - The setup root and every non-spatial subpath load without Pixi, while Canvas and PivotViewer fail specifically on the missing optional peer until it is installed. -- Supported Arc versions load from the packed artifact. +- Declared Arc peer versions are exercised against the packed artifact. - Representative custom-theme and pass-through consumers compile after following the guide. - Specs, Storybook, package exports, SSR, keyboard/focus behavior, responsive layouts, dark mode, forced colors, and reduced motion pass. - The migration guide works without repository-specific knowledge. - Every packed public JavaScript subpath passes strict TypeScript 6 validation or matches a bounded machine-readable upstream exception with exact installed versions and an unmet removal condition. Components-owned cascades additionally require their matching upstream TS2834/TS2835 root cause in the same compiler run. -Track acceptance evidence in [the UI foundation issue](https://github.com/Cratis/Components/issues/170). +The major PR effect packet owns the exact current release evidence and limitations. diff --git a/Documentation/why-components.md b/Documentation/why-components.md index dde0c55a..67f34460 100644 --- a/Documentation/why-components.md +++ b/Documentation/why-components.md @@ -1,13 +1,13 @@ --- title: Why Components -description: Why Cratis owns a component system around Arc proxies and accessible interaction behavior. +description: Why Components owns React composition around Arc proxies and selected interaction primitives. sidebar: order: 1 --- You can connect an Arc-generated command or query to any React UI. Without Components, every application repeatedly builds command execution state, validation display, dialogs, observable subscriptions, paging, selection, empty/pending states, localization, and accessibility behavior. -Components centralizes that integration behind a stable Cratis-owned API. +Components centralizes that integration behind Components-owned React APIs and documented package subpaths. ## What it removes @@ -17,22 +17,22 @@ Components centralizes that integration behind a stable Cratis-owned API. | Bind each field manually | ` command.name} />` | | Subscribe to query changes and manage pending/empty state | Query-backed Components own the result lifecycle | | Hand-roll list pages, selection, paging, and detail panels | `` composes the screen | -| Reimplement focus, overlays, keyboard interaction, and international dates | Components delegates low-level behavior to React Aria and verifies the result | +| Reimplement focus, overlays, keyboard interaction, and international dates | Components delegates selected low-level primitives to React Aria and exercises the composed behavior in owning specs | ## What Components owns - Public React component APIs and event types - Arc command/query/dialog integration -- Semantic markup and accessibility composition +- Semantic markup plus documented ARIA, focus, and keyboard behavior - Stable `data-cratis-part` names and state attributes - `--cratis-*` design tokens and structural styles -- Product-level behavior specs and migration guarantees +- Product-level behavior specs and current migration mappings React Aria is an internal implementation dependency. Consumers do not type against it or style its internal DOM. -## Custom design systems remain first-class +## Custom styling remains product-owned -Import the baseline theme for a ready-made appearance, or omit it and map product tokens directly onto `--cratis-*`. Every meaningful element has a stable Cratis part, and `pt` accepts ordinary HTML attributes for per-instance customization. +Import the optional baseline theme, or omit it and map product tokens directly onto `--cratis-*`. Documented customizable parts use stable Cratis part names, and components that expose `pt` accept ordinary HTML attributes for those documented parts. This avoids coupling a product design system to a renderer preset, proprietary provider, or internal class roster. @@ -44,6 +44,6 @@ Use native HTML or a product-owned presentational component for a one-off elemen ## Why the foundation changed -Components 3 was backed by PrimeReact 11. PrimeUI licensing still applied through wrappers, renderer types leaked into declarations, and custom products depended on renderer-specific pass-through slots. Components 4 replaces that mandatory foundation with Cratis-owned contracts and open interaction dependencies. +Components 3 used PrimeReact as a declared package foundation. Components 4 does not declare PrimeReact, PrimeIcons, PrimeUI, or PrimeUI themes as dependencies or peers; it replaces those package and renderer contracts with Components-owned markup, types, tokens, and documented parts. Applications retaining direct third-party imports keep their own package and license boundaries. Read [UI foundation](ui-foundation.md) for the decision and [Migrate from Components 3](migration.md) for the consumer steps. diff --git a/README.md b/README.md index 5cf15d29..38ed66e0 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,124 @@ # Cratis Components -## Packages +Components is a React component library aligned with Arc application patterns. + +This is the owning source repository for `@cratis/components`. The current +package uses Cratis-owned React markup, public TypeScript types, design tokens, +stable parts, and state attributes. React Aria is an internal implementation +dependency for selected interaction primitives. [![NPM](https://img.shields.io/npm/v/@cratis/components?label=@cratis/components&logo=npm)](https://www.npmjs.com/package/@cratis/components) +[![Publish](https://github.com/Cratis/Components/actions/workflows/publish.yml/badge.svg)](https://github.com/Cratis/Components/actions/workflows/publish.yml) +[![Documentation](https://github.com/Cratis/Documentation/actions/workflows/docs-site.yml/badge.svg)](https://github.com/Cratis/Documentation/actions/workflows/docs-site.yml) -## Builds +## Start here -[![Publish](https://github.com/Cratis/Components/actions/workflows/publish.yml/badge.svg)](https://github.com/Cratis/Components/actions/workflows/publish.yml) -[![Documentation site](https://github.com/Cratis/Documentation/actions/workflows/pages.yml/badge.svg)](https://github.com/Cratis/Documentation/actions/workflows/pages.yml) +- [Browse the canonical Components documentation](https://cratis.io/components/) +- [Install and mount the provider](#minimal-setup) +- [Choose a component area](#what-components-owns) +- [Inspect the package source](https://github.com/Cratis/Components/tree/main/Source) + +## What Components owns + +| Area | Current package role | +| --- | --- | +| Command input | Typed fields, embedded forms, dialogs, and multi-step command flows | +| Data display | Query-backed tables, local-array tables, list pages, filters, and detail surfaces | +| Application surfaces | Dialogs, notifications, dropdowns, display primitives, page chrome, and toolbars | +| Structured editors | JSON content, JSON Schema, navigation, canvas, pivot, and time-oriented views | +| Styling boundary | Cratis tokens, component styles, an optional baseline theme, and stable parts | + +## Relationship to Arc + +Components consumes generated command and query contracts and React contexts +from Arc packages. Arc owns those application contracts; Components owns the +React markup, public component types, styling tokens, stable parts, and component +behavior in this repository. + +Applications may use Arc without Components. Components does not by itself +establish design-system completeness, accessibility conformance, browser +coverage, or compatibility with every Arc/React/package-version combination. +Verify those properties for the exact application and component profile shipped. + +## Minimal setup + +Install the package: + +```bash +npm install @cratis/components +``` + +Import the semantic tokens and component structure. The baseline theme is +optional: + +```tsx +import '@cratis/components/tokens'; +import '@cratis/components/styles'; +import '@cratis/components/theme'; // optional baseline appearance +import { CratisComponentsProvider } from '@cratis/components'; + +export const App = () => ( + + + +); +``` + +The current package manifest defines the exact React, Arc, Fundamentals, and +optional Pixi peer ranges. Verify those ranges before installing the package. + +## Current boundaries + +- The package manifest, exports, source, and migration guide define the current + Components major-version surface. +- Package existence, examples, Storybook output, and passing checks do not + establish maturity, accessibility conformance, browser coverage, support, + security, or production suitability. +- Direct third-party UI dependencies retained by an application keep their own + package, provider, styling, and license boundaries. +- Use the exact package archive and application profile when evaluating an + upgrade. + +## Documentation and migration + +- [Canonical Components documentation](https://cratis.io/components/) +- [Product-owned documentation source](https://github.com/Cratis/Components/tree/main/Documentation) +- [Package README](./Source/README.md) +- [Components 3 to 4 migration guide](./Source/MIGRATION.md) + +## Migration tooling -## Description +The repository contains a codemod and ESLint rule for moving Components 3 root +namespace imports to the current explicit subpaths. The migration guide owns the +current mapping, command, package coordinate, and limitations. Verify the exact +published package version before running migration tooling outside this +repository. -A collection of React components designed to work seamlessly with the constructs found in the Arc universe. These components provide a rich set of UI elements for building modern applications, including command dialogs, data tables, schema editors, and more. +## Contributing -## Codemods +This is a framework-library repository. [Component source](https://github.com/Cratis/Components/tree/main/Source) +keeps public types, stories, and specifications near each component; export and +package verification lives under `Source/scripts/`. -`Codemods/` holds internal, unpublished codemods that support consumer migrations. The -`remove-root-namespace-imports` codemod rewrites `@cratis/components` root-barrel namespace -imports (`import { Canvas } from '@cratis/components'`) onto their canonical subpath -(`import * as Canvas from '@cratis/components/Canvas'`); see [`Codemods/README.md`](./Codemods/README.md) -for full behavior and the companion `@cratis/components/no-root-barrel-import` ESLint rule. +For root and package README changes, verify the exact files explicitly: -```sh -npx --package @cratis/components-codemods \ - cratis-components-remove-root-namespace-imports +```bash +npx markdownlint-cli2 README.md Source/README.md +npx linkinator README.md Source/README.md --markdown --recurse ``` -## Support +Source changes follow the repository's framework rules and the applicable build, +type, specification, export, package-archive, accessibility-diagnostic, and +Storybook gates. -Cratis is an open community, and we are glad to help users, teams evaluating the stack, and contributors. +## Community and repository -| Channel | Details | -| ------------- | -------------------------------------------------------------------------------------------- | -| Discord | Join the community on [Discord](https://discord.gg/kt4AMpV8WV) for questions and discussions | -| GitHub Issues | [Report bugs or request features](https://github.com/Cratis/Components/issues) | -| Documentation | Read the docs at [cratis.io](https://cratis.io) | +| Path | Destination | +| --- | --- | +| Questions and discussion | [Cratis Discord](https://discord.gg/kt4AMpV8WV) | +| Bugs and feature requests | [GitHub Issues](https://github.com/Cratis/Components/issues) | +| Releases | [GitHub Releases](https://github.com/Cratis/Components/releases) | +| Contributing | [Cratis contribution guide](https://github.com/Cratis/.github/blob/main/contributing.md) | +| Security reports | [Private security reporting](mailto:oss@cratis.io?subject=Security%3A) | +| Source license | [`LICENSE`](./LICENSE) | +| Package notices | [`Source/THIRD_PARTY_NOTICES.md`](./Source/THIRD_PARTY_NOTICES.md) | diff --git a/Source/MIGRATION.md b/Source/MIGRATION.md index 3b013955..c3391e1a 100644 --- a/Source/MIGRATION.md +++ b/Source/MIGRATION.md @@ -1,15 +1,11 @@ # Migrate from Components 3 to 4 -Components 4 replaces the mandatory PrimeReact 11 foundation with Cratis-owned markup, styling contracts, and public types. React Aria supplies accessible interaction behavior internally. Applications no longer install, configure, license, theme, or type against PrimeReact to use Components. +Components 4 replaces the PrimeReact-backed Components 3 foundation with Components-owned markup, styling contracts, and public types. React Aria supplies selected interaction primitives internally. The current Components 4 manifest does not declare PrimeReact, PrimeIcons, PrimeUI, or PrimeUI themes as dependencies or peers; applications retaining direct imports keep their own package and license boundaries. -This is intentionally a major release. Component behavior remains familiar, but rendered markup, styling parts, provider configuration, date entry, and some deprecated props change. +This is a major-version migration. Rendered markup, styling parts, provider configuration, date entry, root imports, and some deprecated props change. :::note -Components 3 remains the compatibility line for an application that cannot migrate yet. A separate PrimeReact compatibility package will not be published unless PrimeTek confirms the applicable OEM and redistribution terms in writing. - -**What staying on Components 3 means.** Components 3 keeps PrimeReact 11 as a peer dependency, and PrimeReact 11 verifies a PrimeUI license key when its provider mounts — on every styling path, including unstyled and the MIT Cratis baseline theme, in development and production. Without a valid key the application shows a fixed _"Invalid PrimeUI License"_ banner. The free Community key is eligibility-limited and must be renewed annually; an expired Community key has a 30-day grace period before the banner returns. See [the Components 2 to 3 guide's licensing section](https://github.com/Cratis/Components/blob/main/Documentation/migration-from-2.md#licensing) for the full terms. - -Components 3 receives security and critical defect fixes as the migration compatibility line; it receives no new features or foundation work. Plan the move to Components 4 rather than treating Components 3 as a steady state. +An application that has not migrated remains on its exact Components 3 package profile, including the third-party dependencies declared by that version. Components 4 does not currently publish a Prime compatibility package. Review the exact package manifests and third-party terms for the version the application keeps. This guide makes no support-window, security-fix, maintenance, or future-package commitment for either major. ::: ## Update dependencies @@ -29,7 +25,7 @@ Keep a Prime package only when your application still imports it directly. Migra Applications using Canvas or PivotViewer must install `pixi.js@^8.20.0`, now an optional peer rather than a nested Components dependency. Align any existing direct Pixi dependency to the same compatible resolution so public Pixi types come from one package instance. Applications using only non-Pixi subpaths do not need it. -The supported Arc peer range remains `>=20.3.1 <23`. +The package declares an Arc peer range of `>=20.3.1 <23`. ## Import from explicit subpaths @@ -85,7 +81,7 @@ This is an intentional Components 4 breaking change. The package root now expose `@cratis/components/CommandForm/fields` is the same module as `@cratis/components/CommandForm` — either subpath resolves identically, so the `CommandForm` row's migration applies to both. -Run the shipped AST-based codemod in preview mode first, then apply it: +Run the migration codemod in preview mode first, then apply it: ```bash npx --package @cratis/components-codemods \ @@ -208,7 +204,7 @@ This removes the old product-token → Prime preset → Prime variable → Crati ## Removed accidental package exports -An audit of the published `exports` map ([#173](https://github.com/Cratis/Components/issues/173)) found implementation-only symbols that were unintentionally reachable from a public subpath — each was exported only because the owning module's barrel used a blanket `export *`, not because it was a supported contract. Components 4 stops re-exporting them from their public barrel; the underlying files keep the symbol for their own internal cross-file use, so this is a package-export change only, not a behavior change. +An audit of the package `exports` map ([#173](https://github.com/Cratis/Components/issues/173)) found implementation-only symbols that were unintentionally reachable from a public subpath — each was exported only because the owning module's barrel used a blanket `export *`, not because it was a supported contract. Components 4 stops re-exporting them from their public barrel; the underlying files keep the symbol for their own internal cross-file use, so this is a package-export change only, not a behavior change. | Removed export | Subpath(s) | Migration | | ------------------------------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -221,7 +217,7 @@ An audit of the published `exports` map ([#173](https://github.com/Cratis/Compon | `DEFAULT_EMOJIS`, `QUICK_ROW_SIZE` | `@cratis/components/Canvas` | Private `recentEmojis`/`rememberEmoji` constants. Not part of the public API. | | `buildFilterValues`, `buildRangeValues`, `RenderedHistogramBucket` | `@cratis/components/Filter` | Private `useFilterState`/`RangeHistogramFilter` helpers. Not part of the public API. | -None of these had a documented contract, and none is required by any other public API in this package. An application that imported one of these directly has no supported replacement to migrate to — inline the equivalent logic, or open an issue describing the use case if the behavior should become a supported public contract. +None of these had a documented contract, and none is required by any other public API in this package. An application that imported one of these directly has no documented replacement to migrate to — inline the equivalent logic, or open an issue describing the use case if the behavior should become a supported public contract. The surfaces this audit confirmed as intentional and kept public — `ToastRecord`, `getToastSnapshot`, `subscribeToToasts`, `ToastDispatch`, `EmojiMemory`, `ChatAuthorKind`, `DEFAULT_TYPE_FORMATS`, `NavigationItem`, `Json`, and `TimeMachine`'s `Properties` — are unchanged and now carry TSDoc explaining their contract and, where relevant, their extension-point role. @@ -322,7 +318,7 @@ A Components 3 / PrimeReact 11 product can start with the Components baseline th For a product-owned compositor, replace renderer part types with `DialogParts`, `StepperParts`, and the complete Toolbar part family: `ToolbarParts`, `ToolbarButtonParts`, `ToolbarGroupParts`, `ToolbarSeparatorParts`, `ToolbarLayoutParts`, `ToolbarSectionParts`, `ToolbarFolderParts`, and `ToolbarFanOutParts`. Keep shaders and measurement wrappers product-owned. Measure stable `data-cratis-part` and state boundaries; pass the integrated Canvas surface through `controlsGlassSurface`; pass `data-product-compositor-*` marker names through `captureAttributes`; and localize actions through `controlsLabels`. -The published migration guide contains the complete mappings and stop conditions for each archetype. +This migration guide records the current mappings and stop conditions for each archetype. Paginator callbacks that formerly returned classes from renderer context must become static Cratis parts plus CSS state selectors: @@ -364,7 +360,7 @@ Pass the parts to either query-backed table: - `id` identifies the focus group rather than a native text input. - The accessible calendar trigger is shown by default; set `showIcon={false}` only for segment-entry-only experiences. - `todayLabel` and `clearLabel` override the provider messages for one picker. -- `showTime` and `hourFormat` remain supported. +- `showTime` and `hourFormat` remain in the current API. ## Update Dropdown styling and semantics @@ -443,10 +439,10 @@ Complete PrimeIcons class strings remain usable where a component accepts `Icon` 6. Exercise dialogs, filtered tables, dates, dropdowns, toasts, and steppers with keyboard-only navigation. 7. Verify light, dark, forced-colors, reduced-motion, and responsive layouts. 8. Run TypeScript, specs, Storybook, and the production build. -9. Import components from their explicit subpath rather than the removed root namespace; apply the mapping table under [Import from explicit subpaths](#import-from-explicit-subpaths), or run the shipped codemod. +9. Import components from their explicit subpath rather than the removed root namespace; apply the mapping table under [Import from explicit subpaths](#import-from-explicit-subpaths), or run the migration codemod. -A TypeScript 6 application using `skipLibCheck: false` may see bounded upstream diagnostics from Pixi's `@webgpu/types` collision with TypeScript's built-in WebGPU declarations, from `@cratis/arc.react`'s published global JSX declarations, or under NodeNext from extensionless declaration imports in the current Arc and Fundamentals packages. Components validates every packed subpath without suppressing these diagnostics; exact versions, codes, affected subpaths, and removal conditions are documented under the published [UI foundation](https://cratis.io/components/ui-foundation/#strict-public-type-validation) explanation and tracked in [#176](https://github.com/Cratis/Components/issues/176). +A TypeScript 6 application using `skipLibCheck: false` may see bounded upstream diagnostics from Pixi's `@webgpu/types` collision with TypeScript's built-in WebGPU declarations, from `@cratis/arc.react`'s published global JSX declarations, or under NodeNext from extensionless declaration imports in the current Arc and Fundamentals packages. Components validates every packed subpath without suppressing these diagnostics; exact versions, codes, affected subpaths, and removal conditions are recorded in the owning repository at `Documentation/ui-foundation.md#strict-public-type-validation` and tracked in [#176](https://github.com/Cratis/Components/issues/176). -For the decision, trade-offs, and validation gates, read the published [UI foundation](https://cratis.io/components/ui-foundation/) explanation. For the older 2.x → 3.x PrimeReact migration, see [Migrate from Components 2 to 3](https://cratis.io/components/migration-from-2/). +For the current decision, trade-offs, and validation gates, read `Documentation/ui-foundation.md` in the owning repository. The older 2.x → 3.x path remains in `Documentation/migration-from-2.md`. -Tracked follow-up remains explicit: [#109](https://github.com/Cratis/Components/issues/109) covers a future Arc React table-state binding, [#178](https://github.com/Cratis/Components/issues/178) covers complete-result server filtering before paging, [#174](https://github.com/Cratis/Components/issues/174) covers remaining localization debt, [#175](https://github.com/Cratis/Components/issues/175) covers locale-aware number input, and [#179](https://github.com/Cratis/Components/issues/179) covers downstream RC pilots before stable release. None is silently implemented by a compatibility flag in Components 4. +Open issues may track adjacent gaps, but they do not establish a public roadmap, support window, stable-release date, or compatibility promise for Components 4. diff --git a/Source/README.md b/Source/README.md index b5701856..9c6f243d 100644 --- a/Source/README.md +++ b/Source/README.md @@ -1,8 +1,15 @@ # @cratis/components -Renderer-independent React components for Cratis Arc commands, queries, dialogs, forms, and application surfaces. +Components is a React component library aligned with Arc application patterns. -Components owns its public markup, TypeScript contracts, styling parts, and design tokens. React Aria supplies low-level accessible interaction behavior internally; consumers do not import or style React Aria. +The package provides React components for Arc commands, queries, dialogs, +forms, and application surfaces. Components owns its public markup, TypeScript +contracts, stable parts, and design tokens. React Aria supplies selected +interaction primitives internally; consumers do not import or style React Aria. + +- [Canonical Components documentation](https://cratis.io/components/) +- [Migration guide](https://github.com/Cratis/Components/blob/main/Source/MIGRATION.md) +- [Private security reporting](mailto:oss@cratis.io?subject=Security%3A) ## Install @@ -10,15 +17,16 @@ Components owns its public markup, TypeScript contracts, styling parts, and desi npm install @cratis/components ``` -Supported peers: +The current package manifest declares these peer dependencies: -- React and React DOM 19 - `@cratis/arc` and `@cratis/arc.react` `>=20.3.1 <23` -- `@cratis/fundamentals` -- `reflect-metadata` -- `tsyringe` +- `@cratis/fundamentals` `^7.10.3` +- optional `pixi.js` `^8.20.0` +- `react` and `react-dom` `^19.0.0` +- `reflect-metadata` `0.2.2` +- `tsyringe` `4.10.0` -PrimeReact, PrimeIcons, PrimeUI themes, and a PrimeUI license are not required. +The current manifest does not declare PrimeReact, PrimeIcons, or PrimeUI packages as dependencies or peers. Applications retaining direct dependencies keep their own package, provider, styling, and license boundaries. `pixi.js@^8.20.0` is an additional **optional** peer, required only by `Canvas` and `PivotViewer` (the Spatial capability profile — see [Import from explicit subpaths](#import-from-explicit-subpaths) below). Every other subpath needs nothing beyond the peers above: @@ -26,7 +34,7 @@ PrimeReact, PrimeIcons, PrimeUI themes, and a PrimeUI license are not required. npm install pixi.js@^8.20.0 ``` -Keep exactly one compatible Pixi resolution across the application and Components; two installed copies produce nominal TypeScript incompatibilities for `PIXI.Container` and pointer-event types even though both satisfy `^8.20.0`. See the published [UI foundation](https://cratis.io/components/ui-foundation/#optional-pixi-clean-no-pixi-core) explanation for why. +Keep exactly one compatible Pixi resolution across the application and Components; two installed copies produce nominal TypeScript incompatibilities for `PIXI.Container` and pointer-event types even when both satisfy `^8.20.0`. The capability-subpath table below identifies the current Pixi-dependent surfaces. ## Styles @@ -43,7 +51,7 @@ A custom product design omits `theme`, imports product CSS after `tokens` and `s ## Provider ```tsx -import { CratisComponentsProvider } from '@cratis/components/Common'; +import { CratisComponentsProvider } from '@cratis/components'; export const App = () => ( @@ -131,13 +139,15 @@ toast.success({ }); ``` -The queue, promise lifecycle, timers, dispatch substitution, accessible frame, and region are Cratis-owned. +The queue, promise lifecycle, timers, dispatch substitution, toast frame, and region are Components-owned implementation surfaces. ## Custom styling -Every meaningful component element carries a stable `data-cratis-part`. Components with per-instance customization expose a typed `pt` object containing ordinary HTML attributes. +Documented customizable component parts use stable `data-cratis-part` names. Components with per-instance customization expose a typed `pt` object containing ordinary HTML attributes for their documented parts. ```tsx +import { Dialog } from '@cratis/components/Dialogs'; +