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
56 changes: 56 additions & 0 deletions .changeset/7166-retire-inert-fieldmeta-copies.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
---
'@object-ui/plugin-grid': patch
---

`ObjectGrid` no longer copies `descriptionField`, `lookupColumns` or `lookupFilters` onto a
relational column's `fieldMeta` (objectui#7166). No behaviour change — all three still reach
the inline lookup picker, by a different seam.

`applyRelationalMeta` writes the copy set onto the `fieldMeta` that `generateColumns` hands
to `<CellRenderer>` as the `field` prop — six JSX passes across the three column-building
paths, and nowhere else. For a relational column that resolves to `LookupCellRenderer`,
which reads exactly `reference_to`, `reference`, `display_field`, `displayField`,
`reference_field` and `options`; a `user` column resolves to `UserCellRenderer`, which
destructures `{ value }` and reads no field meta at all. Measured by receiver rather than by
count: `packages/fields/src/index.tsx`, the file holding **every** cell renderer, contains
**zero** occurrences of the three retired keys, against a control of 22 occurrences of the
`display_field` / `displayField` / `reference_to` spellings the cell does read.

Their only readers off a field meta are `LookupField` and `UserField` — the two **editor**
widgets — and the grid's inline editor does not receive this bag. `renderCellEditor` looks
the field up in the object schema and spreads the whole def into the widget
(`{ name: ctx.column.accessorKey, ...fieldDef }`), so every key a def carries reaches
`LookupField` whether or not it is copied. The copies were dead writes: the objectui#6711
(`reference_to_field`) and objectui#6874 (`titleFormat`) class, arriving from the opposite
direction — those keys had no *declaration*, these have no *reader on this path*.

Two of the three, `descriptionField` and `lookupColumns`, were **added** by objectui#6875 as
its fix, classified from a read-set derivation alone. Its third key, `displayField`, is
genuinely delivered and stays copied — and it is the one that arrived with a rendering test.
⭐ The generalisable lesson, now recorded in both docblocks: **a derivation establishes that
a consumer READS a key; it does not establish that a given BAG is how the consumer gets it.**

- New `__tests__/relationalMetaCopySet-7166.test.tsx` renders both directions. The **cell**:
four lookup columns over one referenced record, differing only in the key under test, all
resolve the same text, while the `displayField` control column resolves something else —
the control is what makes the three zeros readings rather than a fixture that never reached
the lookup path. The **editor**: each retired key still takes effect in the inline picker
with the copy set no longer carrying it — `descriptionField` drives the secondary line,
`lookupColumns` shapes the picker columns, `lookupFilters` scopes the candidates — each
against a sibling control column that declares nothing.
- The three snake_case `legacy-alias` spellings — `description_field`, `lookup_filters`,
`id_field` — have the same reader-side verdict and are **deliberately kept**. They are
recorded as legacy aliases precisely because a host `DataSource` outside these repos may
hand-feed them; that is a producer-side argument, untouched by this reader-side
measurement. Their verdict is now recorded on the table with the open producer question
stated, so the next pass inherits a measurement instead of a silence.
- ⛔ The derivation gate cannot enforce this retirement, and now says so. Its read set is a
union over three consumers, two of which are not fed this bag, so all three retired keys
remain in it and every derived assertion passes whichever verdict they carry. Their absence
is pinned by an explicit hand-written assertion plus the rendering test. Re-scoping the
derivation around the cell alone is a design change to objectui#6875's mechanism and is
filed, not made here.
- The gate is strengthened, not weakened: every `deferred` verdict is now mechanically proved
spec-declared against the installed `FieldSchema`, and the sibling pins
(`relationalMetaCopySet-6711` / `-6874`) turn the retired `lookupFilters` into a live
negative assertion on a fixture that still declares it.
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,11 +68,11 @@ const MANAGER_DEF = {
reference_to_field: 'MUST_NOT_BE_COPIED',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -161,13 +161,18 @@ describe('objectui#6711 — ObjectGrid no longer copies `reference_to_field` ont
expect(meta).not.toHaveProperty('reference_to_field');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,11 +79,11 @@ const MANAGER_DEF = {
reference_to_field: 'x',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -172,13 +172,18 @@ describe('objectui#6874 — ObjectGrid no longer copies `titleFormat` onto field
expect(meta).not.toHaveProperty('titleFormat');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 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
56 changes: 56 additions & 0 deletions .changeset/7166-retire-inert-fieldmeta-copies.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
---
'@object-ui/plugin-grid': patch
---

`ObjectGrid` no longer copies `descriptionField`, `lookupColumns` or `lookupFilters` onto a
relational column's `fieldMeta` (objectui#7166). No behaviour change — all three still reach
the inline lookup picker, by a different seam.

`applyRelationalMeta` writes the copy set onto the `fieldMeta` that `generateColumns` hands
to `<CellRenderer>` as the `field` prop — six JSX passes across the three column-building
paths, and nowhere else. For a relational column that resolves to `LookupCellRenderer`,
which reads exactly `reference_to`, `reference`, `display_field`, `displayField`,
`reference_field` and `options`; a `user` column resolves to `UserCellRenderer`, which
destructures `{ value }` and reads no field meta at all. Measured by receiver rather than by
count: `packages/fields/src/index.tsx`, the file holding **every** cell renderer, contains
**zero** occurrences of the three retired keys, against a control of 22 occurrences of the
`display_field` / `displayField` / `reference_to` spellings the cell does read.

Their only readers off a field meta are `LookupField` and `UserField` — the two **editor**
widgets — and the grid's inline editor does not receive this bag. `renderCellEditor` looks
the field up in the object schema and spreads the whole def into the widget
(`{ name: ctx.column.accessorKey, ...fieldDef }`), so every key a def carries reaches
`LookupField` whether or not it is copied. The copies were dead writes: the objectui#6711
(`reference_to_field`) and objectui#6874 (`titleFormat`) class, arriving from the opposite
direction — those keys had no *declaration*, these have no *reader on this path*.

Two of the three, `descriptionField` and `lookupColumns`, were **added** by objectui#6875 as
its fix, classified from a read-set derivation alone. Its third key, `displayField`, is
genuinely delivered and stays copied — and it is the one that arrived with a rendering test.
⭐ The generalisable lesson, now recorded in both docblocks: **a derivation establishes that
a consumer READS a key; it does not establish that a given BAG is how the consumer gets it.**

- New `__tests__/relationalMetaCopySet-7166.test.tsx` renders both directions. The **cell**:
four lookup columns over one referenced record, differing only in the key under test, all
resolve the same text, while the `displayField` control column resolves something else —
the control is what makes the three zeros readings rather than a fixture that never reached
the lookup path. The **editor**: each retired key still takes effect in the inline picker
with the copy set no longer carrying it — `descriptionField` drives the secondary line,
`lookupColumns` shapes the picker columns, `lookupFilters` scopes the candidates — each
against a sibling control column that declares nothing.
- The three snake_case `legacy-alias` spellings — `description_field`, `lookup_filters`,
`id_field` — have the same reader-side verdict and are **deliberately kept**. They are
recorded as legacy aliases precisely because a host `DataSource` outside these repos may
hand-feed them; that is a producer-side argument, untouched by this reader-side
measurement. Their verdict is now recorded on the table with the open producer question
stated, so the next pass inherits a measurement instead of a silence.
- ⛔ The derivation gate cannot enforce this retirement, and now says so. Its read set is a
union over three consumers, two of which are not fed this bag, so all three retired keys
remain in it and every derived assertion passes whichever verdict they carry. Their absence
is pinned by an explicit hand-written assertion plus the rendering test. Re-scoping the
derivation around the cell alone is a design change to objectui#6875's mechanism and is
filed, not made here.
- The gate is strengthened, not weakened: every `deferred` verdict is now mechanically proved
spec-declared against the installed `FieldSchema`, and the sibling pins
(`relationalMetaCopySet-6711` / `-6874`) turn the retired `lookupFilters` into a live
negative assertion on a fixture that still declares it.
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,11 +68,11 @@ const MANAGER_DEF = {
reference_to_field: 'MUST_NOT_BE_COPIED',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -161,13 +161,18 @@ describe('objectui#6711 — ObjectGrid no longer copies `reference_to_field` ont
expect(meta).not.toHaveProperty('reference_to_field');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,11 +79,11 @@ const MANAGER_DEF = {
reference_to_field: 'x',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -172,13 +172,18 @@ describe('objectui#6874 — ObjectGrid no longer copies `titleFormat` onto field
expect(meta).not.toHaveProperty('titleFormat');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Loading
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
56 changes: 56 additions & 0 deletions .changeset/7166-retire-inert-fieldmeta-copies.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
---
'@object-ui/plugin-grid': patch
---

`ObjectGrid` no longer copies `descriptionField`, `lookupColumns` or `lookupFilters` onto a
relational column's `fieldMeta` (objectui#7166). No behaviour change — all three still reach
the inline lookup picker, by a different seam.

`applyRelationalMeta` writes the copy set onto the `fieldMeta` that `generateColumns` hands
to `<CellRenderer>` as the `field` prop — six JSX passes across the three column-building
paths, and nowhere else. For a relational column that resolves to `LookupCellRenderer`,
which reads exactly `reference_to`, `reference`, `display_field`, `displayField`,
`reference_field` and `options`; a `user` column resolves to `UserCellRenderer`, which
destructures `{ value }` and reads no field meta at all. Measured by receiver rather than by
count: `packages/fields/src/index.tsx`, the file holding **every** cell renderer, contains
**zero** occurrences of the three retired keys, against a control of 22 occurrences of the
`display_field` / `displayField` / `reference_to` spellings the cell does read.

Their only readers off a field meta are `LookupField` and `UserField` — the two **editor**
widgets — and the grid's inline editor does not receive this bag. `renderCellEditor` looks
the field up in the object schema and spreads the whole def into the widget
(`{ name: ctx.column.accessorKey, ...fieldDef }`), so every key a def carries reaches
`LookupField` whether or not it is copied. The copies were dead writes: the objectui#6711
(`reference_to_field`) and objectui#6874 (`titleFormat`) class, arriving from the opposite
direction — those keys had no *declaration*, these have no *reader on this path*.

Two of the three, `descriptionField` and `lookupColumns`, were **added** by objectui#6875 as
its fix, classified from a read-set derivation alone. Its third key, `displayField`, is
genuinely delivered and stays copied — and it is the one that arrived with a rendering test.
⭐ The generalisable lesson, now recorded in both docblocks: **a derivation establishes that
a consumer READS a key; it does not establish that a given BAG is how the consumer gets it.**

- New `__tests__/relationalMetaCopySet-7166.test.tsx` renders both directions. The **cell**:
four lookup columns over one referenced record, differing only in the key under test, all
resolve the same text, while the `displayField` control column resolves something else —
the control is what makes the three zeros readings rather than a fixture that never reached
the lookup path. The **editor**: each retired key still takes effect in the inline picker
with the copy set no longer carrying it — `descriptionField` drives the secondary line,
`lookupColumns` shapes the picker columns, `lookupFilters` scopes the candidates — each
against a sibling control column that declares nothing.
- The three snake_case `legacy-alias` spellings — `description_field`, `lookup_filters`,
`id_field` — have the same reader-side verdict and are **deliberately kept**. They are
recorded as legacy aliases precisely because a host `DataSource` outside these repos may
hand-feed them; that is a producer-side argument, untouched by this reader-side
measurement. Their verdict is now recorded on the table with the open producer question
stated, so the next pass inherits a measurement instead of a silence.
- ⛔ The derivation gate cannot enforce this retirement, and now says so. Its read set is a
union over three consumers, two of which are not fed this bag, so all three retired keys
remain in it and every derived assertion passes whichever verdict they carry. Their absence
is pinned by an explicit hand-written assertion plus the rendering test. Re-scoping the
derivation around the cell alone is a design change to objectui#6875's mechanism and is
filed, not made here.
- The gate is strengthened, not weakened: every `deferred` verdict is now mechanically proved
spec-declared against the installed `FieldSchema`, and the sibling pins
(`relationalMetaCopySet-6711` / `-6874`) turn the retired `lookupFilters` into a live
negative assertion on a fixture that still declares it.
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,11 +68,11 @@ const MANAGER_DEF = {
reference_to_field: 'MUST_NOT_BE_COPIED',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -161,13 +161,18 @@ describe('objectui#6711 — ObjectGrid no longer copies `reference_to_field` ont
expect(meta).not.toHaveProperty('reference_to_field');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,11 +79,11 @@ const MANAGER_DEF = {
reference_to_field: 'x',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -172,13 +172,18 @@ describe('objectui#6874 — ObjectGrid no longer copies `titleFormat` onto field
expect(meta).not.toHaveProperty('titleFormat');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Loading
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 > 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
56 changes: 56 additions & 0 deletions .changeset/7166-retire-inert-fieldmeta-copies.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
---
'@object-ui/plugin-grid': patch
---

`ObjectGrid` no longer copies `descriptionField`, `lookupColumns` or `lookupFilters` onto a
relational column's `fieldMeta` (objectui#7166). No behaviour change — all three still reach
the inline lookup picker, by a different seam.

`applyRelationalMeta` writes the copy set onto the `fieldMeta` that `generateColumns` hands
to `<CellRenderer>` as the `field` prop — six JSX passes across the three column-building
paths, and nowhere else. For a relational column that resolves to `LookupCellRenderer`,
which reads exactly `reference_to`, `reference`, `display_field`, `displayField`,
`reference_field` and `options`; a `user` column resolves to `UserCellRenderer`, which
destructures `{ value }` and reads no field meta at all. Measured by receiver rather than by
count: `packages/fields/src/index.tsx`, the file holding **every** cell renderer, contains
**zero** occurrences of the three retired keys, against a control of 22 occurrences of the
`display_field` / `displayField` / `reference_to` spellings the cell does read.

Their only readers off a field meta are `LookupField` and `UserField` — the two **editor**
widgets — and the grid's inline editor does not receive this bag. `renderCellEditor` looks
the field up in the object schema and spreads the whole def into the widget
(`{ name: ctx.column.accessorKey, ...fieldDef }`), so every key a def carries reaches
`LookupField` whether or not it is copied. The copies were dead writes: the objectui#6711
(`reference_to_field`) and objectui#6874 (`titleFormat`) class, arriving from the opposite
direction — those keys had no *declaration*, these have no *reader on this path*.

Two of the three, `descriptionField` and `lookupColumns`, were **added** by objectui#6875 as
its fix, classified from a read-set derivation alone. Its third key, `displayField`, is
genuinely delivered and stays copied — and it is the one that arrived with a rendering test.
⭐ The generalisable lesson, now recorded in both docblocks: **a derivation establishes that
a consumer READS a key; it does not establish that a given BAG is how the consumer gets it.**

- New `__tests__/relationalMetaCopySet-7166.test.tsx` renders both directions. The **cell**:
four lookup columns over one referenced record, differing only in the key under test, all
resolve the same text, while the `displayField` control column resolves something else —
the control is what makes the three zeros readings rather than a fixture that never reached
the lookup path. The **editor**: each retired key still takes effect in the inline picker
with the copy set no longer carrying it — `descriptionField` drives the secondary line,
`lookupColumns` shapes the picker columns, `lookupFilters` scopes the candidates — each
against a sibling control column that declares nothing.
- The three snake_case `legacy-alias` spellings — `description_field`, `lookup_filters`,
`id_field` — have the same reader-side verdict and are **deliberately kept**. They are
recorded as legacy aliases precisely because a host `DataSource` outside these repos may
hand-feed them; that is a producer-side argument, untouched by this reader-side
measurement. Their verdict is now recorded on the table with the open producer question
stated, so the next pass inherits a measurement instead of a silence.
- ⛔ The derivation gate cannot enforce this retirement, and now says so. Its read set is a
union over three consumers, two of which are not fed this bag, so all three retired keys
remain in it and every derived assertion passes whichever verdict they carry. Their absence
is pinned by an explicit hand-written assertion plus the rendering test. Re-scoping the
derivation around the cell alone is a design change to objectui#6875's mechanism and is
filed, not made here.
- The gate is strengthened, not weakened: every `deferred` verdict is now mechanically proved
spec-declared against the installed `FieldSchema`, and the sibling pins
(`relationalMetaCopySet-6711` / `-6874`) turn the retired `lookupFilters` into a live
negative assertion on a fixture that still declares it.
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,11 +68,11 @@ const MANAGER_DEF = {
reference_to_field: 'MUST_NOT_BE_COPIED',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -161,13 +161,18 @@ describe('objectui#6711 — ObjectGrid no longer copies `reference_to_field` ont
expect(meta).not.toHaveProperty('reference_to_field');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,11 +79,11 @@ const MANAGER_DEF = {
reference_to_field: 'x',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -172,13 +172,18 @@ describe('objectui#6874 — ObjectGrid no longer copies `titleFormat` onto field
expect(meta).not.toHaveProperty('titleFormat');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Loading
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
56 changes: 56 additions & 0 deletions .changeset/7166-retire-inert-fieldmeta-copies.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
---
'@object-ui/plugin-grid': patch
---

`ObjectGrid` no longer copies `descriptionField`, `lookupColumns` or `lookupFilters` onto a
relational column's `fieldMeta` (objectui#7166). No behaviour change — all three still reach
the inline lookup picker, by a different seam.

`applyRelationalMeta` writes the copy set onto the `fieldMeta` that `generateColumns` hands
to `<CellRenderer>` as the `field` prop — six JSX passes across the three column-building
paths, and nowhere else. For a relational column that resolves to `LookupCellRenderer`,
which reads exactly `reference_to`, `reference`, `display_field`, `displayField`,
`reference_field` and `options`; a `user` column resolves to `UserCellRenderer`, which
destructures `{ value }` and reads no field meta at all. Measured by receiver rather than by
count: `packages/fields/src/index.tsx`, the file holding **every** cell renderer, contains
**zero** occurrences of the three retired keys, against a control of 22 occurrences of the
`display_field` / `displayField` / `reference_to` spellings the cell does read.

Their only readers off a field meta are `LookupField` and `UserField` — the two **editor**
widgets — and the grid's inline editor does not receive this bag. `renderCellEditor` looks
the field up in the object schema and spreads the whole def into the widget
(`{ name: ctx.column.accessorKey, ...fieldDef }`), so every key a def carries reaches
`LookupField` whether or not it is copied. The copies were dead writes: the objectui#6711
(`reference_to_field`) and objectui#6874 (`titleFormat`) class, arriving from the opposite
direction — those keys had no *declaration*, these have no *reader on this path*.

Two of the three, `descriptionField` and `lookupColumns`, were **added** by objectui#6875 as
its fix, classified from a read-set derivation alone. Its third key, `displayField`, is
genuinely delivered and stays copied — and it is the one that arrived with a rendering test.
⭐ The generalisable lesson, now recorded in both docblocks: **a derivation establishes that
a consumer READS a key; it does not establish that a given BAG is how the consumer gets it.**

- New `__tests__/relationalMetaCopySet-7166.test.tsx` renders both directions. The **cell**:
four lookup columns over one referenced record, differing only in the key under test, all
resolve the same text, while the `displayField` control column resolves something else —
the control is what makes the three zeros readings rather than a fixture that never reached
the lookup path. The **editor**: each retired key still takes effect in the inline picker
with the copy set no longer carrying it — `descriptionField` drives the secondary line,
`lookupColumns` shapes the picker columns, `lookupFilters` scopes the candidates — each
against a sibling control column that declares nothing.
- The three snake_case `legacy-alias` spellings — `description_field`, `lookup_filters`,
`id_field` — have the same reader-side verdict and are **deliberately kept**. They are
recorded as legacy aliases precisely because a host `DataSource` outside these repos may
hand-feed them; that is a producer-side argument, untouched by this reader-side
measurement. Their verdict is now recorded on the table with the open producer question
stated, so the next pass inherits a measurement instead of a silence.
- ⛔ The derivation gate cannot enforce this retirement, and now says so. Its read set is a
union over three consumers, two of which are not fed this bag, so all three retired keys
remain in it and every derived assertion passes whichever verdict they carry. Their absence
is pinned by an explicit hand-written assertion plus the rendering test. Re-scoping the
derivation around the cell alone is a design change to objectui#6875's mechanism and is
filed, not made here.
- The gate is strengthened, not weakened: every `deferred` verdict is now mechanically proved
spec-declared against the installed `FieldSchema`, and the sibling pins
(`relationalMetaCopySet-6711` / `-6874`) turn the retired `lookupFilters` into a live
negative assertion on a fixture that still declares it.
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,11 +68,11 @@ const MANAGER_DEF = {
reference_to_field: 'MUST_NOT_BE_COPIED',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -161,13 +161,18 @@ describe('objectui#6711 — ObjectGrid no longer copies `reference_to_field` ont
expect(meta).not.toHaveProperty('reference_to_field');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,11 +79,11 @@ const MANAGER_DEF = {
reference_to_field: 'x',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -172,13 +172,18 @@ describe('objectui#6874 — ObjectGrid no longer copies `titleFormat` onto field
expect(meta).not.toHaveProperty('titleFormat');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Loading
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
56 changes: 56 additions & 0 deletions .changeset/7166-retire-inert-fieldmeta-copies.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
---
'@object-ui/plugin-grid': patch
---

`ObjectGrid` no longer copies `descriptionField`, `lookupColumns` or `lookupFilters` onto a
relational column's `fieldMeta` (objectui#7166). No behaviour change — all three still reach
the inline lookup picker, by a different seam.

`applyRelationalMeta` writes the copy set onto the `fieldMeta` that `generateColumns` hands
to `<CellRenderer>` as the `field` prop — six JSX passes across the three column-building
paths, and nowhere else. For a relational column that resolves to `LookupCellRenderer`,
which reads exactly `reference_to`, `reference`, `display_field`, `displayField`,
`reference_field` and `options`; a `user` column resolves to `UserCellRenderer`, which
destructures `{ value }` and reads no field meta at all. Measured by receiver rather than by
count: `packages/fields/src/index.tsx`, the file holding **every** cell renderer, contains
**zero** occurrences of the three retired keys, against a control of 22 occurrences of the
`display_field` / `displayField` / `reference_to` spellings the cell does read.

Their only readers off a field meta are `LookupField` and `UserField` — the two **editor**
widgets — and the grid's inline editor does not receive this bag. `renderCellEditor` looks
the field up in the object schema and spreads the whole def into the widget
(`{ name: ctx.column.accessorKey, ...fieldDef }`), so every key a def carries reaches
`LookupField` whether or not it is copied. The copies were dead writes: the objectui#6711
(`reference_to_field`) and objectui#6874 (`titleFormat`) class, arriving from the opposite
direction — those keys had no *declaration*, these have no *reader on this path*.

Two of the three, `descriptionField` and `lookupColumns`, were **added** by objectui#6875 as
its fix, classified from a read-set derivation alone. Its third key, `displayField`, is
genuinely delivered and stays copied — and it is the one that arrived with a rendering test.
⭐ The generalisable lesson, now recorded in both docblocks: **a derivation establishes that
a consumer READS a key; it does not establish that a given BAG is how the consumer gets it.**

- New `__tests__/relationalMetaCopySet-7166.test.tsx` renders both directions. The **cell**:
four lookup columns over one referenced record, differing only in the key under test, all
resolve the same text, while the `displayField` control column resolves something else —
the control is what makes the three zeros readings rather than a fixture that never reached
the lookup path. The **editor**: each retired key still takes effect in the inline picker
with the copy set no longer carrying it — `descriptionField` drives the secondary line,
`lookupColumns` shapes the picker columns, `lookupFilters` scopes the candidates — each
against a sibling control column that declares nothing.
- The three snake_case `legacy-alias` spellings — `description_field`, `lookup_filters`,
`id_field` — have the same reader-side verdict and are **deliberately kept**. They are
recorded as legacy aliases precisely because a host `DataSource` outside these repos may
hand-feed them; that is a producer-side argument, untouched by this reader-side
measurement. Their verdict is now recorded on the table with the open producer question
stated, so the next pass inherits a measurement instead of a silence.
- ⛔ The derivation gate cannot enforce this retirement, and now says so. Its read set is a
union over three consumers, two of which are not fed this bag, so all three retired keys
remain in it and every derived assertion passes whichever verdict they carry. Their absence
is pinned by an explicit hand-written assertion plus the rendering test. Re-scoping the
derivation around the cell alone is a design change to objectui#6875's mechanism and is
filed, not made here.
- The gate is strengthened, not weakened: every `deferred` verdict is now mechanically proved
spec-declared against the installed `FieldSchema`, and the sibling pins
(`relationalMetaCopySet-6711` / `-6874`) turn the retired `lookupFilters` into a live
negative assertion on a fixture that still declares it.
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,11 +68,11 @@ const MANAGER_DEF = {
reference_to_field: 'MUST_NOT_BE_COPIED',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -161,13 +161,18 @@ describe('objectui#6711 — ObjectGrid no longer copies `reference_to_field` ont
expect(meta).not.toHaveProperty('reference_to_field');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,11 +79,11 @@ const MANAGER_DEF = {
reference_to_field: 'x',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -172,13 +172,18 @@ describe('objectui#6874 — ObjectGrid no longer copies `titleFormat` onto field
expect(meta).not.toHaveProperty('titleFormat');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Loading
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
56 changes: 56 additions & 0 deletions .changeset/7166-retire-inert-fieldmeta-copies.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
---
'@object-ui/plugin-grid': patch
---

`ObjectGrid` no longer copies `descriptionField`, `lookupColumns` or `lookupFilters` onto a
relational column's `fieldMeta` (objectui#7166). No behaviour change — all three still reach
the inline lookup picker, by a different seam.

`applyRelationalMeta` writes the copy set onto the `fieldMeta` that `generateColumns` hands
to `<CellRenderer>` as the `field` prop — six JSX passes across the three column-building
paths, and nowhere else. For a relational column that resolves to `LookupCellRenderer`,
which reads exactly `reference_to`, `reference`, `display_field`, `displayField`,
`reference_field` and `options`; a `user` column resolves to `UserCellRenderer`, which
destructures `{ value }` and reads no field meta at all. Measured by receiver rather than by
count: `packages/fields/src/index.tsx`, the file holding **every** cell renderer, contains
**zero** occurrences of the three retired keys, against a control of 22 occurrences of the
`display_field` / `displayField` / `reference_to` spellings the cell does read.

Their only readers off a field meta are `LookupField` and `UserField` — the two **editor**
widgets — and the grid's inline editor does not receive this bag. `renderCellEditor` looks
the field up in the object schema and spreads the whole def into the widget
(`{ name: ctx.column.accessorKey, ...fieldDef }`), so every key a def carries reaches
`LookupField` whether or not it is copied. The copies were dead writes: the objectui#6711
(`reference_to_field`) and objectui#6874 (`titleFormat`) class, arriving from the opposite
direction — those keys had no *declaration*, these have no *reader on this path*.

Two of the three, `descriptionField` and `lookupColumns`, were **added** by objectui#6875 as
its fix, classified from a read-set derivation alone. Its third key, `displayField`, is
genuinely delivered and stays copied — and it is the one that arrived with a rendering test.
⭐ The generalisable lesson, now recorded in both docblocks: **a derivation establishes that
a consumer READS a key; it does not establish that a given BAG is how the consumer gets it.**

- New `__tests__/relationalMetaCopySet-7166.test.tsx` renders both directions. The **cell**:
four lookup columns over one referenced record, differing only in the key under test, all
resolve the same text, while the `displayField` control column resolves something else —
the control is what makes the three zeros readings rather than a fixture that never reached
the lookup path. The **editor**: each retired key still takes effect in the inline picker
with the copy set no longer carrying it — `descriptionField` drives the secondary line,
`lookupColumns` shapes the picker columns, `lookupFilters` scopes the candidates — each
against a sibling control column that declares nothing.
- The three snake_case `legacy-alias` spellings — `description_field`, `lookup_filters`,
`id_field` — have the same reader-side verdict and are **deliberately kept**. They are
recorded as legacy aliases precisely because a host `DataSource` outside these repos may
hand-feed them; that is a producer-side argument, untouched by this reader-side
measurement. Their verdict is now recorded on the table with the open producer question
stated, so the next pass inherits a measurement instead of a silence.
- ⛔ The derivation gate cannot enforce this retirement, and now says so. Its read set is a
union over three consumers, two of which are not fed this bag, so all three retired keys
remain in it and every derived assertion passes whichever verdict they carry. Their absence
is pinned by an explicit hand-written assertion plus the rendering test. Re-scoping the
derivation around the cell alone is a design change to objectui#6875's mechanism and is
filed, not made here.
- The gate is strengthened, not weakened: every `deferred` verdict is now mechanically proved
spec-declared against the installed `FieldSchema`, and the sibling pins
(`relationalMetaCopySet-6711` / `-6874`) turn the retired `lookupFilters` into a live
negative assertion on a fixture that still declares it.
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,11 +68,11 @@ const MANAGER_DEF = {
reference_to_field: 'MUST_NOT_BE_COPIED',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -161,13 +161,18 @@ describe('objectui#6711 — ObjectGrid no longer copies `reference_to_field` ont
expect(meta).not.toHaveProperty('reference_to_field');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,11 +79,11 @@ const MANAGER_DEF = {
reference_to_field: 'x',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -172,13 +172,18 @@ describe('objectui#6874 — ObjectGrid no longer copies `titleFormat` onto field
expect(meta).not.toHaveProperty('titleFormat');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Loading
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
56 changes: 56 additions & 0 deletions .changeset/7166-retire-inert-fieldmeta-copies.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
---
'@object-ui/plugin-grid': patch
---

`ObjectGrid` no longer copies `descriptionField`, `lookupColumns` or `lookupFilters` onto a
relational column's `fieldMeta` (objectui#7166). No behaviour change — all three still reach
the inline lookup picker, by a different seam.

`applyRelationalMeta` writes the copy set onto the `fieldMeta` that `generateColumns` hands
to `<CellRenderer>` as the `field` prop — six JSX passes across the three column-building
paths, and nowhere else. For a relational column that resolves to `LookupCellRenderer`,
which reads exactly `reference_to`, `reference`, `display_field`, `displayField`,
`reference_field` and `options`; a `user` column resolves to `UserCellRenderer`, which
destructures `{ value }` and reads no field meta at all. Measured by receiver rather than by
count: `packages/fields/src/index.tsx`, the file holding **every** cell renderer, contains
**zero** occurrences of the three retired keys, against a control of 22 occurrences of the
`display_field` / `displayField` / `reference_to` spellings the cell does read.

Their only readers off a field meta are `LookupField` and `UserField` — the two **editor**
widgets — and the grid's inline editor does not receive this bag. `renderCellEditor` looks
the field up in the object schema and spreads the whole def into the widget
(`{ name: ctx.column.accessorKey, ...fieldDef }`), so every key a def carries reaches
`LookupField` whether or not it is copied. The copies were dead writes: the objectui#6711
(`reference_to_field`) and objectui#6874 (`titleFormat`) class, arriving from the opposite
direction — those keys had no *declaration*, these have no *reader on this path*.

Two of the three, `descriptionField` and `lookupColumns`, were **added** by objectui#6875 as
its fix, classified from a read-set derivation alone. Its third key, `displayField`, is
genuinely delivered and stays copied — and it is the one that arrived with a rendering test.
⭐ The generalisable lesson, now recorded in both docblocks: **a derivation establishes that
a consumer READS a key; it does not establish that a given BAG is how the consumer gets it.**

- New `__tests__/relationalMetaCopySet-7166.test.tsx` renders both directions. The **cell**:
four lookup columns over one referenced record, differing only in the key under test, all
resolve the same text, while the `displayField` control column resolves something else —
the control is what makes the three zeros readings rather than a fixture that never reached
the lookup path. The **editor**: each retired key still takes effect in the inline picker
with the copy set no longer carrying it — `descriptionField` drives the secondary line,
`lookupColumns` shapes the picker columns, `lookupFilters` scopes the candidates — each
against a sibling control column that declares nothing.
- The three snake_case `legacy-alias` spellings — `description_field`, `lookup_filters`,
`id_field` — have the same reader-side verdict and are **deliberately kept**. They are
recorded as legacy aliases precisely because a host `DataSource` outside these repos may
hand-feed them; that is a producer-side argument, untouched by this reader-side
measurement. Their verdict is now recorded on the table with the open producer question
stated, so the next pass inherits a measurement instead of a silence.
- ⛔ The derivation gate cannot enforce this retirement, and now says so. Its read set is a
union over three consumers, two of which are not fed this bag, so all three retired keys
remain in it and every derived assertion passes whichever verdict they carry. Their absence
is pinned by an explicit hand-written assertion plus the rendering test. Re-scoping the
derivation around the cell alone is a design change to objectui#6875's mechanism and is
filed, not made here.
- The gate is strengthened, not weakened: every `deferred` verdict is now mechanically proved
spec-declared against the installed `FieldSchema`, and the sibling pins
(`relationalMetaCopySet-6711` / `-6874`) turn the retired `lookupFilters` into a live
negative assertion on a fixture that still declares it.
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,11 +68,11 @@ const MANAGER_DEF = {
reference_to_field: 'MUST_NOT_BE_COPIED',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -161,13 +161,18 @@ describe('objectui#6711 — ObjectGrid no longer copies `reference_to_field` ont
expect(meta).not.toHaveProperty('reference_to_field');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,11 +79,11 @@ const MANAGER_DEF = {
reference_to_field: 'x',
};

/** The seven keys that survive both retirements — the control. */
/** The six keys that survive every retirement so far — the control. */
const SURVIVING_KEYS = [
'reference_to', 'reference',
'display_field', 'id_field', 'description_field',
'lookup_filters', 'lookupFilters',
'lookup_filters',
] as const;

const ROWS = [{ id: 'r1', name: 'Tower T1', manager: 'u1' }];
Expand DownExpand Up@@ -172,13 +172,18 @@ describe('objectui#6874 — ObjectGrid no longer copies `titleFormat` onto field
expect(meta).not.toHaveProperty('titleFormat');
});

it(`still copies the seven surviving relational keys (${name})`, async () => {
it(`still copies the six surviving relational keys (${name})`, async () => {
const meta = await renderAndCaptureMeta(schemaExtra);
for (const key of SURVIVING_KEYS) {
expect(meta).toHaveProperty(key);
}
expect(meta.reference_to).toBe('users');
expect(meta.display_field).toBe('name');
// objectui#7166 retired `lookupFilters` from the copy set — its only
// reader is an editor widget, which `renderCellEditor` feeds from the
// schema def. The fixture above still declares it, so this absence is a
// reading and not a fixture that never offered the key.
expect(meta).not.toHaveProperty('lookupFilters');
});
}
});
Loading
Loading