Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .changeset/5942-retire-mobile-component-config.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
---
'@object-ui/types': minor
'@object-ui/mobile': minor
---

**Removes a published export.** Retire the `MobileComponentConfig` type
(objectui#5942, ADR-0049 enforce-or-remove). The name is deleted from
`@object-ui/types` and from `@object-ui/mobile`, which re-exported it — after
this release `import type { MobileComponentConfig }` from either package is a
compile error, not a deprecation warning.

`MobileComponentConfig` published a four-key "mobile component schema
extension" — `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` —
and nothing read it. Re-measured on current `main` before anything was deleted:
the type had exactly four code mentions repo-wide — its own declaration, one
doc-comment cross-reference, and the two barrel re-exports. It had **no mount
point at all**: no type mounted it as a property, nothing extended it, and no
renderer, hook or adapter annotated, cast to or imported it. A sweep of the
example apps and the `objectstack` sibling checkout found zero authors. Every
read-shape probe returned zero against a control lit in the same run.

That makes it stricter than the usual case: not merely a surface whose values
were unimplemented, but a container with no path by which any authored value
could reach a renderer. objectui#4919 removed its last member
(`mobileOverrides`), which is what left the container itself inert.

Removed outright rather than kept as a `?: never` tombstone, on this package's
own discriminator: a tombstone steers authors to a named live replacement key
(`crud.ts` `confirm` to `confirmText`; `data-display.ts` `hoverable`/`striped`
to `data-table`), or keeps loud a key the docs taught as working. Neither
applies — the whole interface goes, so there is no surviving object to hang a
`never` key on, and no documentation ever described it
(`skills/objectui/guides/mobile.md` teaches the hooks, never this type). Same
zero-pull, no-successor shape as `MobileOverrides` (objectui#4919) and
`AccordionItem.icon` / `ToggleGroupItem.icon`.

## Upgrading

**No behaviour changes and there is nothing to migrate at runtime.** An object
authored against this type did nothing before and does nothing now; what
changes is that the contract no longer claims otherwise, so the mistake
surfaces at authoring time instead of silently type-checking.

- **You imported the type only** (the only thing that was possible — nothing
accepted it as a value): delete the import. If you kept a local config object
annotated with it, drop the annotation; the object was never passed anywhere
that read it.
- **You actually wanted the behaviour:** it exists, and it is not being
retired. It lives in `@object-ui/mobile` as React hooks, which is where the
working code always was — `useResponsive` / `ResponsiveContainer` for
`responsive`, `useGesture` for `gestures`, `usePullToRefresh` for
`pullToRefresh`. `infiniteScroll` has no hook; it was never implemented in
any form. See `skills/objectui/guides/mobile.md`.
- **You want a declarative mobile config surface:** that re-enters deliberately
as designed product surface on its own card, with the renderer that reads it
landing in the same change as the declaration — not by restoring this
declaration.

**Do not follow the compiler's suggestion.** TypeScript reports the removal from
`@object-ui/types` as TS2724 and appends `Did you mean 'ComponentConfig'?`. That
is a lexical near-match, not a migration target: `ComponentConfig` is the
renderer **registration** record (`{ type: string; component: T }`, extending
`ComponentMeta`) and has nothing to do with mobile configuration. The import
from `@object-ui/mobile` gets a plain TS2305 with no suggestion at all.

Marked `minor`, not `major`, per this repo's version-alignment rule, which
reserves `major` for following `@objectstack` across a major (AGENTS.md
版本号策略) — the same classification objectui#4919's identically breaking type
removal used. **Breaking for TypeScript consumers of the name only.**

Follow-up, deliberately not widened into this change: `MobileResponsiveConfig`
and `GestureConfig` were consumed only by this container and are now
zero-consumer published types themselves. Filed as objectui#7519 for triage.
1 change: 0 additions & 1 deletion packages/mobile/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
SpecGestureConfig,
SwipeGestureConfig,
PinchGestureConfig,
Expand Down
1 change: 0 additions & 1 deletion packages/types/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -623,7 +623,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
// The retired `@objectstack/spec/ui` touch vocabulary, now owned here —
// see the "Spec Touch Vocabulary" note in `./mobile` (objectstack#4988).
// `SPEC_GESTURE_TYPES` is its runtime witness and is exported as a VALUE
Expand Down
61 changes: 39 additions & 22 deletions packages/types/src/mobile.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,7 +35,7 @@ export type { BreakpointName };
export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;

/**
* Responsive layout configuration for objectui's **mobile component overrides**.
* Responsive layout configuration for the mobile renderer's box layout.
*
* Renamed off the spec's `ResponsiveConfig` name (objectstack#4115): the two
* configure responsiveness through different vocabularies, and this package
Expand All@@ -46,8 +46,14 @@ export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;
* `{ breakpoint, hiddenOn, columns: {xs..2xl}, order: {xs..2xl} }` — arranging a
* node within a grid. This one is the mobile renderer's box config: `columns`
* also accepts a bare number, plus `gap`, `padding`, `stackOnMobile` /
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`. It is
* consumed only by {@link MobileComponentConfig}.
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`.
*
* It currently has NO consumer: its only one was retired by objectui#5942 (PR
* objectui#7526), so this type is still exported from `@object-ui/types` and
* `@object-ui/mobile` and is mounted nowhere. Whether it is retired in turn or
* given a renderer is open as objectui#7519 — a product call rather than a
* mechanical one, because the spec name-ownership tripwire named next outlives
* the type either way.
*
* Tripwire: `__tests__/page-nav-misc-spec-parity.test.ts` fails if the spec ever
* claims this name, so the alias cannot outlive its reason.
Expand DownExpand Up@@ -279,25 +285,36 @@ export interface GestureContext {
rotation?: number;
}

/** Mobile component schema extension */
export interface MobileComponentConfig {
/** Responsive configuration */
responsive?: MobileResponsiveConfig;
/** Touch gesture handlers */
gestures?: GestureConfig[];
/** Pull-to-refresh configuration */
pullToRefresh?: {
enabled: boolean;
threshold?: number;
onRefresh?: string;
};
/** Infinite scroll configuration */
infiniteScroll?: {
enabled: boolean;
threshold?: number;
loadMore?: string;
};
}
// RETIRED (objectui#5942, ADR-0049 enforce-or-remove): `MobileComponentConfig`
// — the free-floating "mobile component schema extension" that published
// `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` — is gone, not
// narrowed. It never had a MOUNT POINT: no type mounted it as a property, no
// declaration extended it, and nothing in this repo, the example apps or the
// `objectstack` sibling checkout annotated, cast to or imported it outside the
// two barrel re-exports. A value written against it could not reach a renderer
// by any path, so all four keys behaved identically — they did nothing.
// objectui#4919 removed its last member (`mobileOverrides`), which is what left
// the container itself inert.
//
// Removed outright rather than kept as a `?: never` carcass, on this package's
// own discriminator: a tombstone exists to steer authors to a named live
// replacement KEY (`crud.ts` `confirm` -> `confirmText`; `data-display.ts`
// `hoverable`/`striped` -> `data-table`), or to keep loud a key the docs taught
// as working. Neither applies. There is no surviving object to hang a `never`
// key on — the whole interface goes — and no documentation ever described it:
// `skills/objectui/guides/mobile.md` teaches the HOOKS and never this type.
// Same zero-pull, no-successor shape as `MobileOverrides` (objectui#4919), and
// as `AccordionItem.icon` / `ToggleGroupItem.icon` before it.
//
// No BEHAVIOUR is retired here. What the four keys named lives in
// `@object-ui/mobile` as real React hooks — `useResponsive` /
// `ResponsiveContainer`, `useGesture`, `usePullToRefresh` — which is where the
// working code always was; only the declaration nothing read is gone.
//
// Reopen condition: a declarative mobile component-config surface re-enters as
// designed product surface on its own card, with the renderer that READS it
// landing in the same change as the declaration. Re-adding the declaration
// alone is the declare-without-enforce shape this removal exists to close.

// ============================================================================
// Spec Touch Vocabulary (formerly `@objectstack/spec/ui`)
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .changeset/5942-retire-mobile-component-config.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
---
'@object-ui/types': minor
'@object-ui/mobile': minor
---

**Removes a published export.** Retire the `MobileComponentConfig` type
(objectui#5942, ADR-0049 enforce-or-remove). The name is deleted from
`@object-ui/types` and from `@object-ui/mobile`, which re-exported it — after
this release `import type { MobileComponentConfig }` from either package is a
compile error, not a deprecation warning.

`MobileComponentConfig` published a four-key "mobile component schema
extension" — `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` —
and nothing read it. Re-measured on current `main` before anything was deleted:
the type had exactly four code mentions repo-wide — its own declaration, one
doc-comment cross-reference, and the two barrel re-exports. It had **no mount
point at all**: no type mounted it as a property, nothing extended it, and no
renderer, hook or adapter annotated, cast to or imported it. A sweep of the
example apps and the `objectstack` sibling checkout found zero authors. Every
read-shape probe returned zero against a control lit in the same run.

That makes it stricter than the usual case: not merely a surface whose values
were unimplemented, but a container with no path by which any authored value
could reach a renderer. objectui#4919 removed its last member
(`mobileOverrides`), which is what left the container itself inert.

Removed outright rather than kept as a `?: never` tombstone, on this package's
own discriminator: a tombstone steers authors to a named live replacement key
(`crud.ts` `confirm` to `confirmText`; `data-display.ts` `hoverable`/`striped`
to `data-table`), or keeps loud a key the docs taught as working. Neither
applies — the whole interface goes, so there is no surviving object to hang a
`never` key on, and no documentation ever described it
(`skills/objectui/guides/mobile.md` teaches the hooks, never this type). Same
zero-pull, no-successor shape as `MobileOverrides` (objectui#4919) and
`AccordionItem.icon` / `ToggleGroupItem.icon`.

## Upgrading

**No behaviour changes and there is nothing to migrate at runtime.** An object
authored against this type did nothing before and does nothing now; what
changes is that the contract no longer claims otherwise, so the mistake
surfaces at authoring time instead of silently type-checking.

- **You imported the type only** (the only thing that was possible — nothing
accepted it as a value): delete the import. If you kept a local config object
annotated with it, drop the annotation; the object was never passed anywhere
that read it.
- **You actually wanted the behaviour:** it exists, and it is not being
retired. It lives in `@object-ui/mobile` as React hooks, which is where the
working code always was — `useResponsive` / `ResponsiveContainer` for
`responsive`, `useGesture` for `gestures`, `usePullToRefresh` for
`pullToRefresh`. `infiniteScroll` has no hook; it was never implemented in
any form. See `skills/objectui/guides/mobile.md`.
- **You want a declarative mobile config surface:** that re-enters deliberately
as designed product surface on its own card, with the renderer that reads it
landing in the same change as the declaration — not by restoring this
declaration.

**Do not follow the compiler's suggestion.** TypeScript reports the removal from
`@object-ui/types` as TS2724 and appends `Did you mean 'ComponentConfig'?`. That
is a lexical near-match, not a migration target: `ComponentConfig` is the
renderer **registration** record (`{ type: string; component: T }`, extending
`ComponentMeta`) and has nothing to do with mobile configuration. The import
from `@object-ui/mobile` gets a plain TS2305 with no suggestion at all.

Marked `minor`, not `major`, per this repo's version-alignment rule, which
reserves `major` for following `@objectstack` across a major (AGENTS.md
版本号策略) — the same classification objectui#4919's identically breaking type
removal used. **Breaking for TypeScript consumers of the name only.**

Follow-up, deliberately not widened into this change: `MobileResponsiveConfig`
and `GestureConfig` were consumed only by this container and are now
zero-consumer published types themselves. Filed as objectui#7519 for triage.
1 change: 0 additions & 1 deletion packages/mobile/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
SpecGestureConfig,
SwipeGestureConfig,
PinchGestureConfig,
Expand Down
1 change: 0 additions & 1 deletion packages/types/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -623,7 +623,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
// The retired `@objectstack/spec/ui` touch vocabulary, now owned here —
// see the "Spec Touch Vocabulary" note in `./mobile` (objectstack#4988).
// `SPEC_GESTURE_TYPES` is its runtime witness and is exported as a VALUE
Expand Down
61 changes: 39 additions & 22 deletions packages/types/src/mobile.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,7 +35,7 @@ export type { BreakpointName };
export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;

/**
* Responsive layout configuration for objectui's **mobile component overrides**.
* Responsive layout configuration for the mobile renderer's box layout.
*
* Renamed off the spec's `ResponsiveConfig` name (objectstack#4115): the two
* configure responsiveness through different vocabularies, and this package
Expand All@@ -46,8 +46,14 @@ export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;
* `{ breakpoint, hiddenOn, columns: {xs..2xl}, order: {xs..2xl} }` — arranging a
* node within a grid. This one is the mobile renderer's box config: `columns`
* also accepts a bare number, plus `gap`, `padding`, `stackOnMobile` /
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`. It is
* consumed only by {@link MobileComponentConfig}.
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`.
*
* It currently has NO consumer: its only one was retired by objectui#5942 (PR
* objectui#7526), so this type is still exported from `@object-ui/types` and
* `@object-ui/mobile` and is mounted nowhere. Whether it is retired in turn or
* given a renderer is open as objectui#7519 — a product call rather than a
* mechanical one, because the spec name-ownership tripwire named next outlives
* the type either way.
*
* Tripwire: `__tests__/page-nav-misc-spec-parity.test.ts` fails if the spec ever
* claims this name, so the alias cannot outlive its reason.
Expand DownExpand Up@@ -279,25 +285,36 @@ export interface GestureContext {
rotation?: number;
}

/** Mobile component schema extension */
export interface MobileComponentConfig {
/** Responsive configuration */
responsive?: MobileResponsiveConfig;
/** Touch gesture handlers */
gestures?: GestureConfig[];
/** Pull-to-refresh configuration */
pullToRefresh?: {
enabled: boolean;
threshold?: number;
onRefresh?: string;
};
/** Infinite scroll configuration */
infiniteScroll?: {
enabled: boolean;
threshold?: number;
loadMore?: string;
};
}
// RETIRED (objectui#5942, ADR-0049 enforce-or-remove): `MobileComponentConfig`
// — the free-floating "mobile component schema extension" that published
// `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` — is gone, not
// narrowed. It never had a MOUNT POINT: no type mounted it as a property, no
// declaration extended it, and nothing in this repo, the example apps or the
// `objectstack` sibling checkout annotated, cast to or imported it outside the
// two barrel re-exports. A value written against it could not reach a renderer
// by any path, so all four keys behaved identically — they did nothing.
// objectui#4919 removed its last member (`mobileOverrides`), which is what left
// the container itself inert.
//
// Removed outright rather than kept as a `?: never` carcass, on this package's
// own discriminator: a tombstone exists to steer authors to a named live
// replacement KEY (`crud.ts` `confirm` -> `confirmText`; `data-display.ts`
// `hoverable`/`striped` -> `data-table`), or to keep loud a key the docs taught
// as working. Neither applies. There is no surviving object to hang a `never`
// key on — the whole interface goes — and no documentation ever described it:
// `skills/objectui/guides/mobile.md` teaches the HOOKS and never this type.
// Same zero-pull, no-successor shape as `MobileOverrides` (objectui#4919), and
// as `AccordionItem.icon` / `ToggleGroupItem.icon` before it.
//
// No BEHAVIOUR is retired here. What the four keys named lives in
// `@object-ui/mobile` as real React hooks — `useResponsive` /
// `ResponsiveContainer`, `useGesture`, `usePullToRefresh` — which is where the
// working code always was; only the declaration nothing read is gone.
//
// Reopen condition: a declarative mobile component-config surface re-enters as
// designed product surface on its own card, with the renderer that READS it
// landing in the same change as the declaration. Re-adding the declaration
// alone is the declare-without-enforce shape this removal exists to close.

// ============================================================================
// Spec Touch Vocabulary (formerly `@objectstack/spec/ui`)
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .changeset/5942-retire-mobile-component-config.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
---
'@object-ui/types': minor
'@object-ui/mobile': minor
---

**Removes a published export.** Retire the `MobileComponentConfig` type
(objectui#5942, ADR-0049 enforce-or-remove). The name is deleted from
`@object-ui/types` and from `@object-ui/mobile`, which re-exported it — after
this release `import type { MobileComponentConfig }` from either package is a
compile error, not a deprecation warning.

`MobileComponentConfig` published a four-key "mobile component schema
extension" — `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` —
and nothing read it. Re-measured on current `main` before anything was deleted:
the type had exactly four code mentions repo-wide — its own declaration, one
doc-comment cross-reference, and the two barrel re-exports. It had **no mount
point at all**: no type mounted it as a property, nothing extended it, and no
renderer, hook or adapter annotated, cast to or imported it. A sweep of the
example apps and the `objectstack` sibling checkout found zero authors. Every
read-shape probe returned zero against a control lit in the same run.

That makes it stricter than the usual case: not merely a surface whose values
were unimplemented, but a container with no path by which any authored value
could reach a renderer. objectui#4919 removed its last member
(`mobileOverrides`), which is what left the container itself inert.

Removed outright rather than kept as a `?: never` tombstone, on this package's
own discriminator: a tombstone steers authors to a named live replacement key
(`crud.ts` `confirm` to `confirmText`; `data-display.ts` `hoverable`/`striped`
to `data-table`), or keeps loud a key the docs taught as working. Neither
applies — the whole interface goes, so there is no surviving object to hang a
`never` key on, and no documentation ever described it
(`skills/objectui/guides/mobile.md` teaches the hooks, never this type). Same
zero-pull, no-successor shape as `MobileOverrides` (objectui#4919) and
`AccordionItem.icon` / `ToggleGroupItem.icon`.

## Upgrading

**No behaviour changes and there is nothing to migrate at runtime.** An object
authored against this type did nothing before and does nothing now; what
changes is that the contract no longer claims otherwise, so the mistake
surfaces at authoring time instead of silently type-checking.

- **You imported the type only** (the only thing that was possible — nothing
accepted it as a value): delete the import. If you kept a local config object
annotated with it, drop the annotation; the object was never passed anywhere
that read it.
- **You actually wanted the behaviour:** it exists, and it is not being
retired. It lives in `@object-ui/mobile` as React hooks, which is where the
working code always was — `useResponsive` / `ResponsiveContainer` for
`responsive`, `useGesture` for `gestures`, `usePullToRefresh` for
`pullToRefresh`. `infiniteScroll` has no hook; it was never implemented in
any form. See `skills/objectui/guides/mobile.md`.
- **You want a declarative mobile config surface:** that re-enters deliberately
as designed product surface on its own card, with the renderer that reads it
landing in the same change as the declaration — not by restoring this
declaration.

**Do not follow the compiler's suggestion.** TypeScript reports the removal from
`@object-ui/types` as TS2724 and appends `Did you mean 'ComponentConfig'?`. That
is a lexical near-match, not a migration target: `ComponentConfig` is the
renderer **registration** record (`{ type: string; component: T }`, extending
`ComponentMeta`) and has nothing to do with mobile configuration. The import
from `@object-ui/mobile` gets a plain TS2305 with no suggestion at all.

Marked `minor`, not `major`, per this repo's version-alignment rule, which
reserves `major` for following `@objectstack` across a major (AGENTS.md
版本号策略) — the same classification objectui#4919's identically breaking type
removal used. **Breaking for TypeScript consumers of the name only.**

Follow-up, deliberately not widened into this change: `MobileResponsiveConfig`
and `GestureConfig` were consumed only by this container and are now
zero-consumer published types themselves. Filed as objectui#7519 for triage.
1 change: 0 additions & 1 deletion packages/mobile/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
SpecGestureConfig,
SwipeGestureConfig,
PinchGestureConfig,
Expand Down
1 change: 0 additions & 1 deletion packages/types/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -623,7 +623,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
// The retired `@objectstack/spec/ui` touch vocabulary, now owned here —
// see the "Spec Touch Vocabulary" note in `./mobile` (objectstack#4988).
// `SPEC_GESTURE_TYPES` is its runtime witness and is exported as a VALUE
Expand Down
61 changes: 39 additions & 22 deletions packages/types/src/mobile.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,7 +35,7 @@ export type { BreakpointName };
export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;

/**
* Responsive layout configuration for objectui's **mobile component overrides**.
* Responsive layout configuration for the mobile renderer's box layout.
*
* Renamed off the spec's `ResponsiveConfig` name (objectstack#4115): the two
* configure responsiveness through different vocabularies, and this package
Expand All@@ -46,8 +46,14 @@ export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;
* `{ breakpoint, hiddenOn, columns: {xs..2xl}, order: {xs..2xl} }` — arranging a
* node within a grid. This one is the mobile renderer's box config: `columns`
* also accepts a bare number, plus `gap`, `padding`, `stackOnMobile` /
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`. It is
* consumed only by {@link MobileComponentConfig}.
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`.
*
* It currently has NO consumer: its only one was retired by objectui#5942 (PR
* objectui#7526), so this type is still exported from `@object-ui/types` and
* `@object-ui/mobile` and is mounted nowhere. Whether it is retired in turn or
* given a renderer is open as objectui#7519 — a product call rather than a
* mechanical one, because the spec name-ownership tripwire named next outlives
* the type either way.
*
* Tripwire: `__tests__/page-nav-misc-spec-parity.test.ts` fails if the spec ever
* claims this name, so the alias cannot outlive its reason.
Expand DownExpand Up@@ -279,25 +285,36 @@ export interface GestureContext {
rotation?: number;
}

/** Mobile component schema extension */
export interface MobileComponentConfig {
/** Responsive configuration */
responsive?: MobileResponsiveConfig;
/** Touch gesture handlers */
gestures?: GestureConfig[];
/** Pull-to-refresh configuration */
pullToRefresh?: {
enabled: boolean;
threshold?: number;
onRefresh?: string;
};
/** Infinite scroll configuration */
infiniteScroll?: {
enabled: boolean;
threshold?: number;
loadMore?: string;
};
}
// RETIRED (objectui#5942, ADR-0049 enforce-or-remove): `MobileComponentConfig`
// — the free-floating "mobile component schema extension" that published
// `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` — is gone, not
// narrowed. It never had a MOUNT POINT: no type mounted it as a property, no
// declaration extended it, and nothing in this repo, the example apps or the
// `objectstack` sibling checkout annotated, cast to or imported it outside the
// two barrel re-exports. A value written against it could not reach a renderer
// by any path, so all four keys behaved identically — they did nothing.
// objectui#4919 removed its last member (`mobileOverrides`), which is what left
// the container itself inert.
//
// Removed outright rather than kept as a `?: never` carcass, on this package's
// own discriminator: a tombstone exists to steer authors to a named live
// replacement KEY (`crud.ts` `confirm` -> `confirmText`; `data-display.ts`
// `hoverable`/`striped` -> `data-table`), or to keep loud a key the docs taught
// as working. Neither applies. There is no surviving object to hang a `never`
// key on — the whole interface goes — and no documentation ever described it:
// `skills/objectui/guides/mobile.md` teaches the HOOKS and never this type.
// Same zero-pull, no-successor shape as `MobileOverrides` (objectui#4919), and
// as `AccordionItem.icon` / `ToggleGroupItem.icon` before it.
//
// No BEHAVIOUR is retired here. What the four keys named lives in
// `@object-ui/mobile` as real React hooks — `useResponsive` /
// `ResponsiveContainer`, `useGesture`, `usePullToRefresh` — which is where the
// working code always was; only the declaration nothing read is gone.
//
// Reopen condition: a declarative mobile component-config surface re-enters as
// designed product surface on its own card, with the renderer that READS it
// landing in the same change as the declaration. Re-adding the declaration
// alone is the declare-without-enforce shape this removal exists to close.

// ============================================================================
// Spec Touch Vocabulary (formerly `@objectstack/spec/ui`)
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .changeset/5942-retire-mobile-component-config.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
---
'@object-ui/types': minor
'@object-ui/mobile': minor
---

**Removes a published export.** Retire the `MobileComponentConfig` type
(objectui#5942, ADR-0049 enforce-or-remove). The name is deleted from
`@object-ui/types` and from `@object-ui/mobile`, which re-exported it — after
this release `import type { MobileComponentConfig }` from either package is a
compile error, not a deprecation warning.

`MobileComponentConfig` published a four-key "mobile component schema
extension" — `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` —
and nothing read it. Re-measured on current `main` before anything was deleted:
the type had exactly four code mentions repo-wide — its own declaration, one
doc-comment cross-reference, and the two barrel re-exports. It had **no mount
point at all**: no type mounted it as a property, nothing extended it, and no
renderer, hook or adapter annotated, cast to or imported it. A sweep of the
example apps and the `objectstack` sibling checkout found zero authors. Every
read-shape probe returned zero against a control lit in the same run.

That makes it stricter than the usual case: not merely a surface whose values
were unimplemented, but a container with no path by which any authored value
could reach a renderer. objectui#4919 removed its last member
(`mobileOverrides`), which is what left the container itself inert.

Removed outright rather than kept as a `?: never` tombstone, on this package's
own discriminator: a tombstone steers authors to a named live replacement key
(`crud.ts` `confirm` to `confirmText`; `data-display.ts` `hoverable`/`striped`
to `data-table`), or keeps loud a key the docs taught as working. Neither
applies — the whole interface goes, so there is no surviving object to hang a
`never` key on, and no documentation ever described it
(`skills/objectui/guides/mobile.md` teaches the hooks, never this type). Same
zero-pull, no-successor shape as `MobileOverrides` (objectui#4919) and
`AccordionItem.icon` / `ToggleGroupItem.icon`.

## Upgrading

**No behaviour changes and there is nothing to migrate at runtime.** An object
authored against this type did nothing before and does nothing now; what
changes is that the contract no longer claims otherwise, so the mistake
surfaces at authoring time instead of silently type-checking.

- **You imported the type only** (the only thing that was possible — nothing
accepted it as a value): delete the import. If you kept a local config object
annotated with it, drop the annotation; the object was never passed anywhere
that read it.
- **You actually wanted the behaviour:** it exists, and it is not being
retired. It lives in `@object-ui/mobile` as React hooks, which is where the
working code always was — `useResponsive` / `ResponsiveContainer` for
`responsive`, `useGesture` for `gestures`, `usePullToRefresh` for
`pullToRefresh`. `infiniteScroll` has no hook; it was never implemented in
any form. See `skills/objectui/guides/mobile.md`.
- **You want a declarative mobile config surface:** that re-enters deliberately
as designed product surface on its own card, with the renderer that reads it
landing in the same change as the declaration — not by restoring this
declaration.

**Do not follow the compiler's suggestion.** TypeScript reports the removal from
`@object-ui/types` as TS2724 and appends `Did you mean 'ComponentConfig'?`. That
is a lexical near-match, not a migration target: `ComponentConfig` is the
renderer **registration** record (`{ type: string; component: T }`, extending
`ComponentMeta`) and has nothing to do with mobile configuration. The import
from `@object-ui/mobile` gets a plain TS2305 with no suggestion at all.

Marked `minor`, not `major`, per this repo's version-alignment rule, which
reserves `major` for following `@objectstack` across a major (AGENTS.md
版本号策略) — the same classification objectui#4919's identically breaking type
removal used. **Breaking for TypeScript consumers of the name only.**

Follow-up, deliberately not widened into this change: `MobileResponsiveConfig`
and `GestureConfig` were consumed only by this container and are now
zero-consumer published types themselves. Filed as objectui#7519 for triage.
1 change: 0 additions & 1 deletion packages/mobile/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
SpecGestureConfig,
SwipeGestureConfig,
PinchGestureConfig,
Expand Down
1 change: 0 additions & 1 deletion packages/types/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -623,7 +623,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
// The retired `@objectstack/spec/ui` touch vocabulary, now owned here —
// see the "Spec Touch Vocabulary" note in `./mobile` (objectstack#4988).
// `SPEC_GESTURE_TYPES` is its runtime witness and is exported as a VALUE
Expand Down
61 changes: 39 additions & 22 deletions packages/types/src/mobile.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,7 +35,7 @@ export type { BreakpointName };
export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;

/**
* Responsive layout configuration for objectui's **mobile component overrides**.
* Responsive layout configuration for the mobile renderer's box layout.
*
* Renamed off the spec's `ResponsiveConfig` name (objectstack#4115): the two
* configure responsiveness through different vocabularies, and this package
Expand All@@ -46,8 +46,14 @@ export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;
* `{ breakpoint, hiddenOn, columns: {xs..2xl}, order: {xs..2xl} }` — arranging a
* node within a grid. This one is the mobile renderer's box config: `columns`
* also accepts a bare number, plus `gap`, `padding`, `stackOnMobile` /
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`. It is
* consumed only by {@link MobileComponentConfig}.
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`.
*
* It currently has NO consumer: its only one was retired by objectui#5942 (PR
* objectui#7526), so this type is still exported from `@object-ui/types` and
* `@object-ui/mobile` and is mounted nowhere. Whether it is retired in turn or
* given a renderer is open as objectui#7519 — a product call rather than a
* mechanical one, because the spec name-ownership tripwire named next outlives
* the type either way.
*
* Tripwire: `__tests__/page-nav-misc-spec-parity.test.ts` fails if the spec ever
* claims this name, so the alias cannot outlive its reason.
Expand DownExpand Up@@ -279,25 +285,36 @@ export interface GestureContext {
rotation?: number;
}

/** Mobile component schema extension */
export interface MobileComponentConfig {
/** Responsive configuration */
responsive?: MobileResponsiveConfig;
/** Touch gesture handlers */
gestures?: GestureConfig[];
/** Pull-to-refresh configuration */
pullToRefresh?: {
enabled: boolean;
threshold?: number;
onRefresh?: string;
};
/** Infinite scroll configuration */
infiniteScroll?: {
enabled: boolean;
threshold?: number;
loadMore?: string;
};
}
// RETIRED (objectui#5942, ADR-0049 enforce-or-remove): `MobileComponentConfig`
// — the free-floating "mobile component schema extension" that published
// `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` — is gone, not
// narrowed. It never had a MOUNT POINT: no type mounted it as a property, no
// declaration extended it, and nothing in this repo, the example apps or the
// `objectstack` sibling checkout annotated, cast to or imported it outside the
// two barrel re-exports. A value written against it could not reach a renderer
// by any path, so all four keys behaved identically — they did nothing.
// objectui#4919 removed its last member (`mobileOverrides`), which is what left
// the container itself inert.
//
// Removed outright rather than kept as a `?: never` carcass, on this package's
// own discriminator: a tombstone exists to steer authors to a named live
// replacement KEY (`crud.ts` `confirm` -> `confirmText`; `data-display.ts`
// `hoverable`/`striped` -> `data-table`), or to keep loud a key the docs taught
// as working. Neither applies. There is no surviving object to hang a `never`
// key on — the whole interface goes — and no documentation ever described it:
// `skills/objectui/guides/mobile.md` teaches the HOOKS and never this type.
// Same zero-pull, no-successor shape as `MobileOverrides` (objectui#4919), and
// as `AccordionItem.icon` / `ToggleGroupItem.icon` before it.
//
// No BEHAVIOUR is retired here. What the four keys named lives in
// `@object-ui/mobile` as real React hooks — `useResponsive` /
// `ResponsiveContainer`, `useGesture`, `usePullToRefresh` — which is where the
// working code always was; only the declaration nothing read is gone.
//
// Reopen condition: a declarative mobile component-config surface re-enters as
// designed product surface on its own card, with the renderer that READS it
// landing in the same change as the declaration. Re-adding the declaration
// alone is the declare-without-enforce shape this removal exists to close.

// ============================================================================
// Spec Touch Vocabulary (formerly `@objectstack/spec/ui`)
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .changeset/5942-retire-mobile-component-config.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
---
'@object-ui/types': minor
'@object-ui/mobile': minor
---

**Removes a published export.** Retire the `MobileComponentConfig` type
(objectui#5942, ADR-0049 enforce-or-remove). The name is deleted from
`@object-ui/types` and from `@object-ui/mobile`, which re-exported it — after
this release `import type { MobileComponentConfig }` from either package is a
compile error, not a deprecation warning.

`MobileComponentConfig` published a four-key "mobile component schema
extension" — `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` —
and nothing read it. Re-measured on current `main` before anything was deleted:
the type had exactly four code mentions repo-wide — its own declaration, one
doc-comment cross-reference, and the two barrel re-exports. It had **no mount
point at all**: no type mounted it as a property, nothing extended it, and no
renderer, hook or adapter annotated, cast to or imported it. A sweep of the
example apps and the `objectstack` sibling checkout found zero authors. Every
read-shape probe returned zero against a control lit in the same run.

That makes it stricter than the usual case: not merely a surface whose values
were unimplemented, but a container with no path by which any authored value
could reach a renderer. objectui#4919 removed its last member
(`mobileOverrides`), which is what left the container itself inert.

Removed outright rather than kept as a `?: never` tombstone, on this package's
own discriminator: a tombstone steers authors to a named live replacement key
(`crud.ts` `confirm` to `confirmText`; `data-display.ts` `hoverable`/`striped`
to `data-table`), or keeps loud a key the docs taught as working. Neither
applies — the whole interface goes, so there is no surviving object to hang a
`never` key on, and no documentation ever described it
(`skills/objectui/guides/mobile.md` teaches the hooks, never this type). Same
zero-pull, no-successor shape as `MobileOverrides` (objectui#4919) and
`AccordionItem.icon` / `ToggleGroupItem.icon`.

## Upgrading

**No behaviour changes and there is nothing to migrate at runtime.** An object
authored against this type did nothing before and does nothing now; what
changes is that the contract no longer claims otherwise, so the mistake
surfaces at authoring time instead of silently type-checking.

- **You imported the type only** (the only thing that was possible — nothing
accepted it as a value): delete the import. If you kept a local config object
annotated with it, drop the annotation; the object was never passed anywhere
that read it.
- **You actually wanted the behaviour:** it exists, and it is not being
retired. It lives in `@object-ui/mobile` as React hooks, which is where the
working code always was — `useResponsive` / `ResponsiveContainer` for
`responsive`, `useGesture` for `gestures`, `usePullToRefresh` for
`pullToRefresh`. `infiniteScroll` has no hook; it was never implemented in
any form. See `skills/objectui/guides/mobile.md`.
- **You want a declarative mobile config surface:** that re-enters deliberately
as designed product surface on its own card, with the renderer that reads it
landing in the same change as the declaration — not by restoring this
declaration.

**Do not follow the compiler's suggestion.** TypeScript reports the removal from
`@object-ui/types` as TS2724 and appends `Did you mean 'ComponentConfig'?`. That
is a lexical near-match, not a migration target: `ComponentConfig` is the
renderer **registration** record (`{ type: string; component: T }`, extending
`ComponentMeta`) and has nothing to do with mobile configuration. The import
from `@object-ui/mobile` gets a plain TS2305 with no suggestion at all.

Marked `minor`, not `major`, per this repo's version-alignment rule, which
reserves `major` for following `@objectstack` across a major (AGENTS.md
版本号策略) — the same classification objectui#4919's identically breaking type
removal used. **Breaking for TypeScript consumers of the name only.**

Follow-up, deliberately not widened into this change: `MobileResponsiveConfig`
and `GestureConfig` were consumed only by this container and are now
zero-consumer published types themselves. Filed as objectui#7519 for triage.
1 change: 0 additions & 1 deletion packages/mobile/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
SpecGestureConfig,
SwipeGestureConfig,
PinchGestureConfig,
Expand Down
1 change: 0 additions & 1 deletion packages/types/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -623,7 +623,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
// The retired `@objectstack/spec/ui` touch vocabulary, now owned here —
// see the "Spec Touch Vocabulary" note in `./mobile` (objectstack#4988).
// `SPEC_GESTURE_TYPES` is its runtime witness and is exported as a VALUE
Expand Down
61 changes: 39 additions & 22 deletions packages/types/src/mobile.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,7 +35,7 @@ export type { BreakpointName };
export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;

/**
* Responsive layout configuration for objectui's **mobile component overrides**.
* Responsive layout configuration for the mobile renderer's box layout.
*
* Renamed off the spec's `ResponsiveConfig` name (objectstack#4115): the two
* configure responsiveness through different vocabularies, and this package
Expand All@@ -46,8 +46,14 @@ export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;
* `{ breakpoint, hiddenOn, columns: {xs..2xl}, order: {xs..2xl} }` — arranging a
* node within a grid. This one is the mobile renderer's box config: `columns`
* also accepts a bare number, plus `gap`, `padding`, `stackOnMobile` /
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`. It is
* consumed only by {@link MobileComponentConfig}.
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`.
*
* It currently has NO consumer: its only one was retired by objectui#5942 (PR
* objectui#7526), so this type is still exported from `@object-ui/types` and
* `@object-ui/mobile` and is mounted nowhere. Whether it is retired in turn or
* given a renderer is open as objectui#7519 — a product call rather than a
* mechanical one, because the spec name-ownership tripwire named next outlives
* the type either way.
*
* Tripwire: `__tests__/page-nav-misc-spec-parity.test.ts` fails if the spec ever
* claims this name, so the alias cannot outlive its reason.
Expand DownExpand Up@@ -279,25 +285,36 @@ export interface GestureContext {
rotation?: number;
}

/** Mobile component schema extension */
export interface MobileComponentConfig {
/** Responsive configuration */
responsive?: MobileResponsiveConfig;
/** Touch gesture handlers */
gestures?: GestureConfig[];
/** Pull-to-refresh configuration */
pullToRefresh?: {
enabled: boolean;
threshold?: number;
onRefresh?: string;
};
/** Infinite scroll configuration */
infiniteScroll?: {
enabled: boolean;
threshold?: number;
loadMore?: string;
};
}
// RETIRED (objectui#5942, ADR-0049 enforce-or-remove): `MobileComponentConfig`
// — the free-floating "mobile component schema extension" that published
// `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` — is gone, not
// narrowed. It never had a MOUNT POINT: no type mounted it as a property, no
// declaration extended it, and nothing in this repo, the example apps or the
// `objectstack` sibling checkout annotated, cast to or imported it outside the
// two barrel re-exports. A value written against it could not reach a renderer
// by any path, so all four keys behaved identically — they did nothing.
// objectui#4919 removed its last member (`mobileOverrides`), which is what left
// the container itself inert.
//
// Removed outright rather than kept as a `?: never` carcass, on this package's
// own discriminator: a tombstone exists to steer authors to a named live
// replacement KEY (`crud.ts` `confirm` -> `confirmText`; `data-display.ts`
// `hoverable`/`striped` -> `data-table`), or to keep loud a key the docs taught
// as working. Neither applies. There is no surviving object to hang a `never`
// key on — the whole interface goes — and no documentation ever described it:
// `skills/objectui/guides/mobile.md` teaches the HOOKS and never this type.
// Same zero-pull, no-successor shape as `MobileOverrides` (objectui#4919), and
// as `AccordionItem.icon` / `ToggleGroupItem.icon` before it.
//
// No BEHAVIOUR is retired here. What the four keys named lives in
// `@object-ui/mobile` as real React hooks — `useResponsive` /
// `ResponsiveContainer`, `useGesture`, `usePullToRefresh` — which is where the
// working code always was; only the declaration nothing read is gone.
//
// Reopen condition: a declarative mobile component-config surface re-enters as
// designed product surface on its own card, with the renderer that READS it
// landing in the same change as the declaration. Re-adding the declaration
// alone is the declare-without-enforce shape this removal exists to close.

// ============================================================================
// Spec Touch Vocabulary (formerly `@objectstack/spec/ui`)
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .changeset/5942-retire-mobile-component-config.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
---
'@object-ui/types': minor
'@object-ui/mobile': minor
---

**Removes a published export.** Retire the `MobileComponentConfig` type
(objectui#5942, ADR-0049 enforce-or-remove). The name is deleted from
`@object-ui/types` and from `@object-ui/mobile`, which re-exported it — after
this release `import type { MobileComponentConfig }` from either package is a
compile error, not a deprecation warning.

`MobileComponentConfig` published a four-key "mobile component schema
extension" — `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` —
and nothing read it. Re-measured on current `main` before anything was deleted:
the type had exactly four code mentions repo-wide — its own declaration, one
doc-comment cross-reference, and the two barrel re-exports. It had **no mount
point at all**: no type mounted it as a property, nothing extended it, and no
renderer, hook or adapter annotated, cast to or imported it. A sweep of the
example apps and the `objectstack` sibling checkout found zero authors. Every
read-shape probe returned zero against a control lit in the same run.

That makes it stricter than the usual case: not merely a surface whose values
were unimplemented, but a container with no path by which any authored value
could reach a renderer. objectui#4919 removed its last member
(`mobileOverrides`), which is what left the container itself inert.

Removed outright rather than kept as a `?: never` tombstone, on this package's
own discriminator: a tombstone steers authors to a named live replacement key
(`crud.ts` `confirm` to `confirmText`; `data-display.ts` `hoverable`/`striped`
to `data-table`), or keeps loud a key the docs taught as working. Neither
applies — the whole interface goes, so there is no surviving object to hang a
`never` key on, and no documentation ever described it
(`skills/objectui/guides/mobile.md` teaches the hooks, never this type). Same
zero-pull, no-successor shape as `MobileOverrides` (objectui#4919) and
`AccordionItem.icon` / `ToggleGroupItem.icon`.

## Upgrading

**No behaviour changes and there is nothing to migrate at runtime.** An object
authored against this type did nothing before and does nothing now; what
changes is that the contract no longer claims otherwise, so the mistake
surfaces at authoring time instead of silently type-checking.

- **You imported the type only** (the only thing that was possible — nothing
accepted it as a value): delete the import. If you kept a local config object
annotated with it, drop the annotation; the object was never passed anywhere
that read it.
- **You actually wanted the behaviour:** it exists, and it is not being
retired. It lives in `@object-ui/mobile` as React hooks, which is where the
working code always was — `useResponsive` / `ResponsiveContainer` for
`responsive`, `useGesture` for `gestures`, `usePullToRefresh` for
`pullToRefresh`. `infiniteScroll` has no hook; it was never implemented in
any form. See `skills/objectui/guides/mobile.md`.
- **You want a declarative mobile config surface:** that re-enters deliberately
as designed product surface on its own card, with the renderer that reads it
landing in the same change as the declaration — not by restoring this
declaration.

**Do not follow the compiler's suggestion.** TypeScript reports the removal from
`@object-ui/types` as TS2724 and appends `Did you mean 'ComponentConfig'?`. That
is a lexical near-match, not a migration target: `ComponentConfig` is the
renderer **registration** record (`{ type: string; component: T }`, extending
`ComponentMeta`) and has nothing to do with mobile configuration. The import
from `@object-ui/mobile` gets a plain TS2305 with no suggestion at all.

Marked `minor`, not `major`, per this repo's version-alignment rule, which
reserves `major` for following `@objectstack` across a major (AGENTS.md
版本号策略) — the same classification objectui#4919's identically breaking type
removal used. **Breaking for TypeScript consumers of the name only.**

Follow-up, deliberately not widened into this change: `MobileResponsiveConfig`
and `GestureConfig` were consumed only by this container and are now
zero-consumer published types themselves. Filed as objectui#7519 for triage.
1 change: 0 additions & 1 deletion packages/mobile/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
SpecGestureConfig,
SwipeGestureConfig,
PinchGestureConfig,
Expand Down
1 change: 0 additions & 1 deletion packages/types/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -623,7 +623,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
// The retired `@objectstack/spec/ui` touch vocabulary, now owned here —
// see the "Spec Touch Vocabulary" note in `./mobile` (objectstack#4988).
// `SPEC_GESTURE_TYPES` is its runtime witness and is exported as a VALUE
Expand Down
61 changes: 39 additions & 22 deletions packages/types/src/mobile.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,7 +35,7 @@ export type { BreakpointName };
export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;

/**
* Responsive layout configuration for objectui's **mobile component overrides**.
* Responsive layout configuration for the mobile renderer's box layout.
*
* Renamed off the spec's `ResponsiveConfig` name (objectstack#4115): the two
* configure responsiveness through different vocabularies, and this package
Expand All@@ -46,8 +46,14 @@ export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;
* `{ breakpoint, hiddenOn, columns: {xs..2xl}, order: {xs..2xl} }` — arranging a
* node within a grid. This one is the mobile renderer's box config: `columns`
* also accepts a bare number, plus `gap`, `padding`, `stackOnMobile` /
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`. It is
* consumed only by {@link MobileComponentConfig}.
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`.
*
* It currently has NO consumer: its only one was retired by objectui#5942 (PR
* objectui#7526), so this type is still exported from `@object-ui/types` and
* `@object-ui/mobile` and is mounted nowhere. Whether it is retired in turn or
* given a renderer is open as objectui#7519 — a product call rather than a
* mechanical one, because the spec name-ownership tripwire named next outlives
* the type either way.
*
* Tripwire: `__tests__/page-nav-misc-spec-parity.test.ts` fails if the spec ever
* claims this name, so the alias cannot outlive its reason.
Expand DownExpand Up@@ -279,25 +285,36 @@ export interface GestureContext {
rotation?: number;
}

/** Mobile component schema extension */
export interface MobileComponentConfig {
/** Responsive configuration */
responsive?: MobileResponsiveConfig;
/** Touch gesture handlers */
gestures?: GestureConfig[];
/** Pull-to-refresh configuration */
pullToRefresh?: {
enabled: boolean;
threshold?: number;
onRefresh?: string;
};
/** Infinite scroll configuration */
infiniteScroll?: {
enabled: boolean;
threshold?: number;
loadMore?: string;
};
}
// RETIRED (objectui#5942, ADR-0049 enforce-or-remove): `MobileComponentConfig`
// — the free-floating "mobile component schema extension" that published
// `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` — is gone, not
// narrowed. It never had a MOUNT POINT: no type mounted it as a property, no
// declaration extended it, and nothing in this repo, the example apps or the
// `objectstack` sibling checkout annotated, cast to or imported it outside the
// two barrel re-exports. A value written against it could not reach a renderer
// by any path, so all four keys behaved identically — they did nothing.
// objectui#4919 removed its last member (`mobileOverrides`), which is what left
// the container itself inert.
//
// Removed outright rather than kept as a `?: never` carcass, on this package's
// own discriminator: a tombstone exists to steer authors to a named live
// replacement KEY (`crud.ts` `confirm` -> `confirmText`; `data-display.ts`
// `hoverable`/`striped` -> `data-table`), or to keep loud a key the docs taught
// as working. Neither applies. There is no surviving object to hang a `never`
// key on — the whole interface goes — and no documentation ever described it:
// `skills/objectui/guides/mobile.md` teaches the HOOKS and never this type.
// Same zero-pull, no-successor shape as `MobileOverrides` (objectui#4919), and
// as `AccordionItem.icon` / `ToggleGroupItem.icon` before it.
//
// No BEHAVIOUR is retired here. What the four keys named lives in
// `@object-ui/mobile` as real React hooks — `useResponsive` /
// `ResponsiveContainer`, `useGesture`, `usePullToRefresh` — which is where the
// working code always was; only the declaration nothing read is gone.
//
// Reopen condition: a declarative mobile component-config surface re-enters as
// designed product surface on its own card, with the renderer that READS it
// landing in the same change as the declaration. Re-adding the declaration
// alone is the declare-without-enforce shape this removal exists to close.

// ============================================================================
// Spec Touch Vocabulary (formerly `@objectstack/spec/ui`)
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .changeset/5942-retire-mobile-component-config.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
---
'@object-ui/types': minor
'@object-ui/mobile': minor
---

**Removes a published export.** Retire the `MobileComponentConfig` type
(objectui#5942, ADR-0049 enforce-or-remove). The name is deleted from
`@object-ui/types` and from `@object-ui/mobile`, which re-exported it — after
this release `import type { MobileComponentConfig }` from either package is a
compile error, not a deprecation warning.

`MobileComponentConfig` published a four-key "mobile component schema
extension" — `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` —
and nothing read it. Re-measured on current `main` before anything was deleted:
the type had exactly four code mentions repo-wide — its own declaration, one
doc-comment cross-reference, and the two barrel re-exports. It had **no mount
point at all**: no type mounted it as a property, nothing extended it, and no
renderer, hook or adapter annotated, cast to or imported it. A sweep of the
example apps and the `objectstack` sibling checkout found zero authors. Every
read-shape probe returned zero against a control lit in the same run.

That makes it stricter than the usual case: not merely a surface whose values
were unimplemented, but a container with no path by which any authored value
could reach a renderer. objectui#4919 removed its last member
(`mobileOverrides`), which is what left the container itself inert.

Removed outright rather than kept as a `?: never` tombstone, on this package's
own discriminator: a tombstone steers authors to a named live replacement key
(`crud.ts` `confirm` to `confirmText`; `data-display.ts` `hoverable`/`striped`
to `data-table`), or keeps loud a key the docs taught as working. Neither
applies — the whole interface goes, so there is no surviving object to hang a
`never` key on, and no documentation ever described it
(`skills/objectui/guides/mobile.md` teaches the hooks, never this type). Same
zero-pull, no-successor shape as `MobileOverrides` (objectui#4919) and
`AccordionItem.icon` / `ToggleGroupItem.icon`.

## Upgrading

**No behaviour changes and there is nothing to migrate at runtime.** An object
authored against this type did nothing before and does nothing now; what
changes is that the contract no longer claims otherwise, so the mistake
surfaces at authoring time instead of silently type-checking.

- **You imported the type only** (the only thing that was possible — nothing
accepted it as a value): delete the import. If you kept a local config object
annotated with it, drop the annotation; the object was never passed anywhere
that read it.
- **You actually wanted the behaviour:** it exists, and it is not being
retired. It lives in `@object-ui/mobile` as React hooks, which is where the
working code always was — `useResponsive` / `ResponsiveContainer` for
`responsive`, `useGesture` for `gestures`, `usePullToRefresh` for
`pullToRefresh`. `infiniteScroll` has no hook; it was never implemented in
any form. See `skills/objectui/guides/mobile.md`.
- **You want a declarative mobile config surface:** that re-enters deliberately
as designed product surface on its own card, with the renderer that reads it
landing in the same change as the declaration — not by restoring this
declaration.

**Do not follow the compiler's suggestion.** TypeScript reports the removal from
`@object-ui/types` as TS2724 and appends `Did you mean 'ComponentConfig'?`. That
is a lexical near-match, not a migration target: `ComponentConfig` is the
renderer **registration** record (`{ type: string; component: T }`, extending
`ComponentMeta`) and has nothing to do with mobile configuration. The import
from `@object-ui/mobile` gets a plain TS2305 with no suggestion at all.

Marked `minor`, not `major`, per this repo's version-alignment rule, which
reserves `major` for following `@objectstack` across a major (AGENTS.md
版本号策略) — the same classification objectui#4919's identically breaking type
removal used. **Breaking for TypeScript consumers of the name only.**

Follow-up, deliberately not widened into this change: `MobileResponsiveConfig`
and `GestureConfig` were consumed only by this container and are now
zero-consumer published types themselves. Filed as objectui#7519 for triage.
1 change: 0 additions & 1 deletion packages/mobile/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
SpecGestureConfig,
SwipeGestureConfig,
PinchGestureConfig,
Expand Down
1 change: 0 additions & 1 deletion packages/types/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -623,7 +623,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
// The retired `@objectstack/spec/ui` touch vocabulary, now owned here —
// see the "Spec Touch Vocabulary" note in `./mobile` (objectstack#4988).
// `SPEC_GESTURE_TYPES` is its runtime witness and is exported as a VALUE
Expand Down
61 changes: 39 additions & 22 deletions packages/types/src/mobile.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,7 +35,7 @@ export type { BreakpointName };
export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;

/**
* Responsive layout configuration for objectui's **mobile component overrides**.
* Responsive layout configuration for the mobile renderer's box layout.
*
* Renamed off the spec's `ResponsiveConfig` name (objectstack#4115): the two
* configure responsiveness through different vocabularies, and this package
Expand All@@ -46,8 +46,14 @@ export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;
* `{ breakpoint, hiddenOn, columns: {xs..2xl}, order: {xs..2xl} }` — arranging a
* node within a grid. This one is the mobile renderer's box config: `columns`
* also accepts a bare number, plus `gap`, `padding`, `stackOnMobile` /
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`. It is
* consumed only by {@link MobileComponentConfig}.
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`.
*
* It currently has NO consumer: its only one was retired by objectui#5942 (PR
* objectui#7526), so this type is still exported from `@object-ui/types` and
* `@object-ui/mobile` and is mounted nowhere. Whether it is retired in turn or
* given a renderer is open as objectui#7519 — a product call rather than a
* mechanical one, because the spec name-ownership tripwire named next outlives
* the type either way.
*
* Tripwire: `__tests__/page-nav-misc-spec-parity.test.ts` fails if the spec ever
* claims this name, so the alias cannot outlive its reason.
Expand DownExpand Up@@ -279,25 +285,36 @@ export interface GestureContext {
rotation?: number;
}

/** Mobile component schema extension */
export interface MobileComponentConfig {
/** Responsive configuration */
responsive?: MobileResponsiveConfig;
/** Touch gesture handlers */
gestures?: GestureConfig[];
/** Pull-to-refresh configuration */
pullToRefresh?: {
enabled: boolean;
threshold?: number;
onRefresh?: string;
};
/** Infinite scroll configuration */
infiniteScroll?: {
enabled: boolean;
threshold?: number;
loadMore?: string;
};
}
// RETIRED (objectui#5942, ADR-0049 enforce-or-remove): `MobileComponentConfig`
// — the free-floating "mobile component schema extension" that published
// `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` — is gone, not
// narrowed. It never had a MOUNT POINT: no type mounted it as a property, no
// declaration extended it, and nothing in this repo, the example apps or the
// `objectstack` sibling checkout annotated, cast to or imported it outside the
// two barrel re-exports. A value written against it could not reach a renderer
// by any path, so all four keys behaved identically — they did nothing.
// objectui#4919 removed its last member (`mobileOverrides`), which is what left
// the container itself inert.
//
// Removed outright rather than kept as a `?: never` carcass, on this package's
// own discriminator: a tombstone exists to steer authors to a named live
// replacement KEY (`crud.ts` `confirm` -> `confirmText`; `data-display.ts`
// `hoverable`/`striped` -> `data-table`), or to keep loud a key the docs taught
// as working. Neither applies. There is no surviving object to hang a `never`
// key on — the whole interface goes — and no documentation ever described it:
// `skills/objectui/guides/mobile.md` teaches the HOOKS and never this type.
// Same zero-pull, no-successor shape as `MobileOverrides` (objectui#4919), and
// as `AccordionItem.icon` / `ToggleGroupItem.icon` before it.
//
// No BEHAVIOUR is retired here. What the four keys named lives in
// `@object-ui/mobile` as real React hooks — `useResponsive` /
// `ResponsiveContainer`, `useGesture`, `usePullToRefresh` — which is where the
// working code always was; only the declaration nothing read is gone.
//
// Reopen condition: a declarative mobile component-config surface re-enters as
// designed product surface on its own card, with the renderer that READS it
// landing in the same change as the declaration. Re-adding the declaration
// alone is the declare-without-enforce shape this removal exists to close.

// ============================================================================
// Spec Touch Vocabulary (formerly `@objectstack/spec/ui`)
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .changeset/5942-retire-mobile-component-config.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
---
'@object-ui/types': minor
'@object-ui/mobile': minor
---

**Removes a published export.** Retire the `MobileComponentConfig` type
(objectui#5942, ADR-0049 enforce-or-remove). The name is deleted from
`@object-ui/types` and from `@object-ui/mobile`, which re-exported it — after
this release `import type { MobileComponentConfig }` from either package is a
compile error, not a deprecation warning.

`MobileComponentConfig` published a four-key "mobile component schema
extension" — `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` —
and nothing read it. Re-measured on current `main` before anything was deleted:
the type had exactly four code mentions repo-wide — its own declaration, one
doc-comment cross-reference, and the two barrel re-exports. It had **no mount
point at all**: no type mounted it as a property, nothing extended it, and no
renderer, hook or adapter annotated, cast to or imported it. A sweep of the
example apps and the `objectstack` sibling checkout found zero authors. Every
read-shape probe returned zero against a control lit in the same run.

That makes it stricter than the usual case: not merely a surface whose values
were unimplemented, but a container with no path by which any authored value
could reach a renderer. objectui#4919 removed its last member
(`mobileOverrides`), which is what left the container itself inert.

Removed outright rather than kept as a `?: never` tombstone, on this package's
own discriminator: a tombstone steers authors to a named live replacement key
(`crud.ts` `confirm` to `confirmText`; `data-display.ts` `hoverable`/`striped`
to `data-table`), or keeps loud a key the docs taught as working. Neither
applies — the whole interface goes, so there is no surviving object to hang a
`never` key on, and no documentation ever described it
(`skills/objectui/guides/mobile.md` teaches the hooks, never this type). Same
zero-pull, no-successor shape as `MobileOverrides` (objectui#4919) and
`AccordionItem.icon` / `ToggleGroupItem.icon`.

## Upgrading

**No behaviour changes and there is nothing to migrate at runtime.** An object
authored against this type did nothing before and does nothing now; what
changes is that the contract no longer claims otherwise, so the mistake
surfaces at authoring time instead of silently type-checking.

- **You imported the type only** (the only thing that was possible — nothing
accepted it as a value): delete the import. If you kept a local config object
annotated with it, drop the annotation; the object was never passed anywhere
that read it.
- **You actually wanted the behaviour:** it exists, and it is not being
retired. It lives in `@object-ui/mobile` as React hooks, which is where the
working code always was — `useResponsive` / `ResponsiveContainer` for
`responsive`, `useGesture` for `gestures`, `usePullToRefresh` for
`pullToRefresh`. `infiniteScroll` has no hook; it was never implemented in
any form. See `skills/objectui/guides/mobile.md`.
- **You want a declarative mobile config surface:** that re-enters deliberately
as designed product surface on its own card, with the renderer that reads it
landing in the same change as the declaration — not by restoring this
declaration.

**Do not follow the compiler's suggestion.** TypeScript reports the removal from
`@object-ui/types` as TS2724 and appends `Did you mean 'ComponentConfig'?`. That
is a lexical near-match, not a migration target: `ComponentConfig` is the
renderer **registration** record (`{ type: string; component: T }`, extending
`ComponentMeta`) and has nothing to do with mobile configuration. The import
from `@object-ui/mobile` gets a plain TS2305 with no suggestion at all.

Marked `minor`, not `major`, per this repo's version-alignment rule, which
reserves `major` for following `@objectstack` across a major (AGENTS.md
版本号策略) — the same classification objectui#4919's identically breaking type
removal used. **Breaking for TypeScript consumers of the name only.**

Follow-up, deliberately not widened into this change: `MobileResponsiveConfig`
and `GestureConfig` were consumed only by this container and are now
zero-consumer published types themselves. Filed as objectui#7519 for triage.
1 change: 0 additions & 1 deletion packages/mobile/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
SpecGestureConfig,
SwipeGestureConfig,
PinchGestureConfig,
Expand Down
1 change: 0 additions & 1 deletion packages/types/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -623,7 +623,6 @@ export type {
GestureType,
GestureConfig,
GestureContext,
MobileComponentConfig,
// The retired `@objectstack/spec/ui` touch vocabulary, now owned here —
// see the "Spec Touch Vocabulary" note in `./mobile` (objectstack#4988).
// `SPEC_GESTURE_TYPES` is its runtime witness and is exported as a VALUE
Expand Down
61 changes: 39 additions & 22 deletions packages/types/src/mobile.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,7 +35,7 @@ export type { BreakpointName };
export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;

/**
* Responsive layout configuration for objectui's **mobile component overrides**.
* Responsive layout configuration for the mobile renderer's box layout.
*
* Renamed off the spec's `ResponsiveConfig` name (objectstack#4115): the two
* configure responsiveness through different vocabularies, and this package
Expand All@@ -46,8 +46,14 @@ export type ResponsiveValue<T> = T | Partial<Record<BreakpointName, T>>;
* `{ breakpoint, hiddenOn, columns: {xs..2xl}, order: {xs..2xl} }` — arranging a
* node within a grid. This one is the mobile renderer's box config: `columns`
* also accepts a bare number, plus `gap`, `padding`, `stackOnMobile` /
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`. It is
* consumed only by {@link MobileComponentConfig}.
* `stackBreakpoint`, and `hidden`/`showOnly` in place of `hiddenOn`.
*
* It currently has NO consumer: its only one was retired by objectui#5942 (PR
* objectui#7526), so this type is still exported from `@object-ui/types` and
* `@object-ui/mobile` and is mounted nowhere. Whether it is retired in turn or
* given a renderer is open as objectui#7519 — a product call rather than a
* mechanical one, because the spec name-ownership tripwire named next outlives
* the type either way.
*
* Tripwire: `__tests__/page-nav-misc-spec-parity.test.ts` fails if the spec ever
* claims this name, so the alias cannot outlive its reason.
Expand DownExpand Up@@ -279,25 +285,36 @@ export interface GestureContext {
rotation?: number;
}

/** Mobile component schema extension */
export interface MobileComponentConfig {
/** Responsive configuration */
responsive?: MobileResponsiveConfig;
/** Touch gesture handlers */
gestures?: GestureConfig[];
/** Pull-to-refresh configuration */
pullToRefresh?: {
enabled: boolean;
threshold?: number;
onRefresh?: string;
};
/** Infinite scroll configuration */
infiniteScroll?: {
enabled: boolean;
threshold?: number;
loadMore?: string;
};
}
// RETIRED (objectui#5942, ADR-0049 enforce-or-remove): `MobileComponentConfig`
// — the free-floating "mobile component schema extension" that published
// `responsive`, `gestures`, `pullToRefresh` and `infiniteScroll` — is gone, not
// narrowed. It never had a MOUNT POINT: no type mounted it as a property, no
// declaration extended it, and nothing in this repo, the example apps or the
// `objectstack` sibling checkout annotated, cast to or imported it outside the
// two barrel re-exports. A value written against it could not reach a renderer
// by any path, so all four keys behaved identically — they did nothing.
// objectui#4919 removed its last member (`mobileOverrides`), which is what left
// the container itself inert.
//
// Removed outright rather than kept as a `?: never` carcass, on this package's
// own discriminator: a tombstone exists to steer authors to a named live
// replacement KEY (`crud.ts` `confirm` -> `confirmText`; `data-display.ts`
// `hoverable`/`striped` -> `data-table`), or to keep loud a key the docs taught
// as working. Neither applies. There is no surviving object to hang a `never`
// key on — the whole interface goes — and no documentation ever described it:
// `skills/objectui/guides/mobile.md` teaches the HOOKS and never this type.
// Same zero-pull, no-successor shape as `MobileOverrides` (objectui#4919), and
// as `AccordionItem.icon` / `ToggleGroupItem.icon` before it.
//
// No BEHAVIOUR is retired here. What the four keys named lives in
// `@object-ui/mobile` as real React hooks — `useResponsive` /
// `ResponsiveContainer`, `useGesture`, `usePullToRefresh` — which is where the
// working code always was; only the declaration nothing read is gone.
//
// Reopen condition: a declarative mobile component-config surface re-enters as
// designed product surface on its own card, with the renderer that READS it
// landing in the same change as the declaration. Re-adding the declaration
// alone is the declare-without-enforce shape this removal exists to close.

// ============================================================================
// Spec Touch Vocabulary (formerly `@objectstack/spec/ui`)
Expand Down
Loading