diff --git a/README.md b/README.md index 5449fca..68cd6b5 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ archives are vendored under `vendor/zennotes/` with their source identity and checksums (`manifest.json`), and `package-lock.json` pins the complete install. A clean checkout installs them with `npm ci`, without a source clone or sibling repository. The vendored set is the core release -[core-2.81.0-core.h4e6a38a3361b4748](https://github.com/ZenNotes/zennotes/releases/tag/core-2.81.0-core.h4e6a38a3361b4748) -(desktop commit `bfab9fdc`, clean tree). +[core-2.81.1-core.h4d33347386401068](https://github.com/ZenNotes/zennotes/releases/tag/core-2.81.1-core.h4d33347386401068) +(desktop commit `daedf423`, clean tree). `npm run boundaries:check` verifies the pins, installed versions, singleton React/CodeMirror peers, and public export usage. `npm run core:adopt -- ` diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 5cf9855..3fccf00 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -624,7 +624,7 @@ CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_ENTITLEMENTS = ZenWidgets/ZenWidgets.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEVELOPMENT_TEAM = WYY7PK57DM; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = ZenWidgets/Info.plist; @@ -753,7 +753,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = App/App.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEVELOPMENT_TEAM = WYY7PK57DM; INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; @@ -775,7 +775,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = App/App.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEVELOPMENT_TEAM = WYY7PK57DM; INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; @@ -795,7 +795,7 @@ CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEVELOPMENT_TEAM = WYY7PK57DM; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = ShareExtension/Info.plist; @@ -817,7 +817,7 @@ CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_ENTITLEMENTS = ZenWidgets/ZenWidgets.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEVELOPMENT_TEAM = WYY7PK57DM; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = ZenWidgets/Info.plist; @@ -855,7 +855,7 @@ CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEVELOPMENT_TEAM = WYY7PK57DM; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = ShareExtension/Info.plist; diff --git a/package-lock.json b/package-lock.json index f67f454..8ce610b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,9 +32,9 @@ "@lezer/highlight": "^1.2.5", "@replit/codemirror-vim": "^6.4.0", "@xyflow/react": "^12.12.0", - "@zennotes/app-core": "file:vendor/zennotes/zennotes-app-core-2.81.0-core.h4e6a38a3361b4748.tgz", - "@zennotes/bridge-contract": "file:vendor/zennotes/zennotes-bridge-contract-2.81.0-boundaries.h697bb3192aa5970b.tgz", - "@zennotes/shared-domain": "file:vendor/zennotes/zennotes-shared-domain-2.81.0-boundaries.h697bb3192aa5970b.tgz", + "@zennotes/app-core": "file:vendor/zennotes/zennotes-app-core-2.81.1-core.h4d33347386401068.tgz", + "@zennotes/bridge-contract": "file:vendor/zennotes/zennotes-bridge-contract-2.81.1-boundaries.h35527b79ebf7355e.tgz", + "@zennotes/shared-domain": "file:vendor/zennotes/zennotes-shared-domain-2.81.1-boundaries.h35527b79ebf7355e.tgz", "codemirror": "^6.0.1", "dompurify": "^3.4.17", "function-plot": "^1.26.0", @@ -3666,9 +3666,9 @@ } }, "node_modules/@zennotes/app-core": { - "version": "2.81.0-core.h4e6a38a3361b4748", - "resolved": "file:vendor/zennotes/zennotes-app-core-2.81.0-core.h4e6a38a3361b4748.tgz", - "integrity": "sha512-0cEPF3+zsswihP+JCcxqfij+p0ssYxPHpt58EaGDgEx8LiYFdnTP9dnu67WliUNprIdHTKAdkrwmZ6Kc7hJFCQ==", + "version": "2.81.1-core.h4d33347386401068", + "resolved": "file:vendor/zennotes/zennotes-app-core-2.81.1-core.h4d33347386401068.tgz", + "integrity": "sha512-Ksdq8MeaI1cWwnHYemTVAFpm/PPyNI10D+FPHdSqcNHaMPPKQAktI06QKIF9YJk4TFiZcGhL6/jVP0weaX523w==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.18.3", @@ -3698,8 +3698,8 @@ "@replit/codemirror-vim": "^6.3.0", "@terrastruct/d2": "0.1.33", "@xyflow/react": "^12.11.2", - "@zennotes/bridge-contract": "2.81.0-boundaries.h697bb3192aa5970b", - "@zennotes/shared-domain": "2.81.0-boundaries.h697bb3192aa5970b", + "@zennotes/bridge-contract": "2.81.1-boundaries.h35527b79ebf7355e", + "@zennotes/shared-domain": "2.81.1-boundaries.h35527b79ebf7355e", "dompurify": "^3.3.4", "function-plot": "^1.25.3", "gray-matter": "^4.0.3", @@ -3743,19 +3743,19 @@ } }, "node_modules/@zennotes/bridge-contract": { - "version": "2.81.0-boundaries.h697bb3192aa5970b", - "resolved": "file:vendor/zennotes/zennotes-bridge-contract-2.81.0-boundaries.h697bb3192aa5970b.tgz", - "integrity": "sha512-Aukkw1ZsDrTaSZ3L1fUjulNJHFpN8G/uFSeNFYpXxx5NziyL1ZYKlcO+6Mcc47qLKvHUryMhehqILZFJsXcnwQ==", + "version": "2.81.1-boundaries.h35527b79ebf7355e", + "resolved": "file:vendor/zennotes/zennotes-bridge-contract-2.81.1-boundaries.h35527b79ebf7355e.tgz", + "integrity": "sha512-48s1/wqVn1WwviidRDVaOwWP5l6jSvY4Pz8a4Z54vo5P0MaZthVYRDnr+ABh6/9TK4TECeNEIoc0eSLGdVsC7Q==", "license": "MIT" }, "node_modules/@zennotes/shared-domain": { - "version": "2.81.0-boundaries.h697bb3192aa5970b", - "resolved": "file:vendor/zennotes/zennotes-shared-domain-2.81.0-boundaries.h697bb3192aa5970b.tgz", - "integrity": "sha512-sS4/C0A/SSC8GN7cqm8wLUcBWCqenJM/BhfPFmHCKyle24EMJFbs3KPhy/4auLOErXi7Qf+wC0r+kVZmbLaciQ==", + "version": "2.81.1-boundaries.h35527b79ebf7355e", + "resolved": "file:vendor/zennotes/zennotes-shared-domain-2.81.1-boundaries.h35527b79ebf7355e.tgz", + "integrity": "sha512-sdYdnD9Dn5xMiWIs2cAT1Bofi79LW7Xp9pms+WGZyFQ88/eBgmNbF+1k9M+RnG1fTdPHjq3O4j+NC4cndSBUZQ==", "license": "MIT", "dependencies": { "@scure/bip39": "2.4.0", - "@zennotes/bridge-contract": "2.81.0-boundaries.h697bb3192aa5970b", + "@zennotes/bridge-contract": "2.81.1-boundaries.h35527b79ebf7355e", "hash-wasm": "4.12.0", "lz-string": "^1.5.0" } diff --git a/package.json b/package.json index ec8d5f9..2eb7114 100644 --- a/package.json +++ b/package.json @@ -45,9 +45,9 @@ "@lezer/highlight": "^1.2.5", "@replit/codemirror-vim": "^6.4.0", "@xyflow/react": "^12.12.0", - "@zennotes/app-core": "file:vendor/zennotes/zennotes-app-core-2.81.0-core.h4e6a38a3361b4748.tgz", - "@zennotes/bridge-contract": "file:vendor/zennotes/zennotes-bridge-contract-2.81.0-boundaries.h697bb3192aa5970b.tgz", - "@zennotes/shared-domain": "file:vendor/zennotes/zennotes-shared-domain-2.81.0-boundaries.h697bb3192aa5970b.tgz", + "@zennotes/app-core": "file:vendor/zennotes/zennotes-app-core-2.81.1-core.h4d33347386401068.tgz", + "@zennotes/bridge-contract": "file:vendor/zennotes/zennotes-bridge-contract-2.81.1-boundaries.h35527b79ebf7355e.tgz", + "@zennotes/shared-domain": "file:vendor/zennotes/zennotes-shared-domain-2.81.1-boundaries.h35527b79ebf7355e.tgz", "codemirror": "^6.0.1", "dompurify": "^3.4.17", "function-plot": "^1.26.0", diff --git a/src/ui-mobile/mobile.css b/src/ui-mobile/mobile.css index c720cc5..e89debe 100644 --- a/src/ui-mobile/mobile.css +++ b/src/ui-mobile/mobile.css @@ -2258,19 +2258,21 @@ display: none !important; } -/* Core 2.81.0 shows hover-only controls on a screen that cannot hover. The - Table row's Open is one: a hover shortcut laid over the end of the name - cell, so on a phone it hid the end of every long name. The row's page - glyph, left of the name, already opens the page. */ -.zn-mobile.zn-phone tr.group\/row td button.zn-hover-reveal[title='Open page'] { - display: none !important; +/* Core 2.81.1 wraps these tools inside the pane, so none runs off a narrow + one. A phone's line is just short of them: at 402 pt they miss by 11 px, and + the ... menu fell to a line of its own under the rest. Tighter buttons hold + all five on one line down to a 375 pt screen. */ +.zn-mobile.zn-phone + header.glass-header:has(button[title='Toggle the underlying CSV text']) + > .ml-auto { + column-gap: 0.25rem; } -/* The select column keeps its 40 px when a long title widens the Table, so - its box, now always shown, stays clear of the screen's edge. */ -.zn-mobile.zn-phone th.group\/sa.w-10, -.zn-mobile.zn-phone tr.group\/row > td.w-10:first-child { - min-width: 2.5rem; +.zn-mobile.zn-phone + header.glass-header:has(button[title='Toggle the underlying CSV text']) + > .ml-auto + > button.px-3 { + padding-inline: 0.5rem; } /* Comfortable touch targets for rows and the New-row affordance. */ diff --git a/src/ui-mobile/table-touch.test.ts b/src/ui-mobile/table-touch.test.ts index 1e9147a..aa86e0c 100644 --- a/src/ui-mobile/table-touch.test.ts +++ b/src/ui-mobile/table-touch.test.ts @@ -3,38 +3,73 @@ import { readFileSync } from 'node:fs' import { describe, it } from 'node:test' import postcss from 'postcss' -// Core 2.81.0 shows hover-only controls where nothing can hover. On a phone -// the database Table's row Open then sat over the end of every long name, and -// the always-shown select boxes lost their column to a long title. +// Core 2.81.0 showed hover-only controls where nothing can hover, so on a phone +// the database Table's row Open sat over the end of every long name and a long +// title squeezed the always-shown select boxes. The shell hid the one and +// widened the other itself until core 2.81.1 did both; it carries no rule for +// either now, so these pin what it relies on. -const css = postcss.parse(readFileSync(new URL('./mobile.css', import.meta.url), 'utf8')) +const shell = postcss.parse(readFileSync(new URL('./mobile.css', import.meta.url), 'utf8')) +const core = postcss.parse( + readFileSync(new URL('../../node_modules/@zennotes/app-core/dist/styles/index.css', import.meta.url), 'utf8') +) const table = readFileSync( new URL('../../node_modules/@zennotes/app-core/dist/components/DatabaseTableView.js', import.meta.url), 'utf8' ) +const view = readFileSync( + new URL('../../node_modules/@zennotes/app-core/dist/components/DatabaseView.js', import.meta.url), + 'utf8' +) +const button = readFileSync( + new URL('../../node_modules/@zennotes/app-core/dist/components/ui/Button.js', import.meta.url), + 'utf8' +) -function declaration(selector: string, property: string): string | undefined { - let result: string | undefined - css.walkRules((rule) => { - if (!rule.selectors.includes(selector)) return - rule.walkDecls(property, (decl) => { result = decl.value }) +/** The declaration core applies to a selector on a screen that cannot hover. */ +function whereNothingHovers(selector: string, property: string): postcss.Declaration | undefined { + let result: postcss.Declaration | undefined + core.walkAtRules('media', (media) => { + if (media.params !== 'not all and (hover: hover) and (pointer: fine)') return + media.walkRules((rule) => { + if (!rule.selectors.includes(selector)) return + rule.walkDecls(property, (decl) => { result = decl }) + }) }) return result } describe('the database Table on a phone', () => { - it('drops the row Open that covered long names; the page glyph opens the page', () => { - assert.equal( - declaration(".zn-mobile.zn-phone tr.group\\/row td button.zn-hover-reveal[title='Open page']", 'display'), - 'none' - ) - assert.match(table, /zn-hover-reveal absolute right-1\.5/) - assert.match(table, /title: hasContent \? 'Open page' : 'Open page \(empty\)'/) + it('has core drop the row Open that covered long names; the page glyph opens the page', () => { + assert.match(table, /title: "Open page", className: "zn-hover-only absolute right-1\.5/) + const display = whereNothingHovers('.zn-hover-only', 'display') + assert.equal(display?.value, 'none') + assert.equal(display?.important, true) + assert.match(table, /title: hasContent \? 'Open page' : 'Open page \(empty\)', className: \[\s*'flex shrink-0/) }) - it('keeps the select column wide enough for its box', () => { - assert.equal(declaration('.zn-mobile.zn-phone th.group\\/sa.w-10', 'min-width'), '2.5rem') - assert.equal(declaration('.zn-mobile.zn-phone tr.group\\/row > td.w-10:first-child', 'min-width'), '2.5rem') - assert.match(table, /group\/sa w-10/) + it('has core keep the select column wide enough for its box', () => { + assert.match(table, /group\/sa w-10 min-w-10/) + assert.match(table, /_jsx\("td", \{ className: "w-10 min-w-10 /) + }) +}) + +describe('the database header on a phone', () => { + const tools = ".zn-mobile.zn-phone header.glass-header:has(button[title='Toggle the underlying CSV text']) > .ml-auto" + + function shellDeclaration(selector: string, property: string): string | undefined { + let result: string | undefined + shell.walkRules((rule) => { + if (rule.selector.replace(/\s+/g, ' ') !== selector) return + rule.walkDecls(property, (decl) => { result = decl.value }) + }) + return result + } + + it('holds the tools core wraps on one line, so the ... menu keeps its place beside them', () => { + assert.match(view, /"ml-auto flex max-w-full flex-wrap items-center justify-end gap-1\.5"/) + assert.match(button, /px-3/) + assert.equal(shellDeclaration(tools, 'column-gap'), '0.25rem') + assert.equal(shellDeclaration(`${tools} > button.px-3`, 'padding-inline'), '0.5rem') }) }) diff --git a/vendor/zennotes/manifest.json b/vendor/zennotes/manifest.json index 4d11983..2dbfe28 100644 --- a/vendor/zennotes/manifest.json +++ b/vendor/zennotes/manifest.json @@ -1,12 +1,12 @@ { "name": "@zennotes/app-core", - "version": "2.81.0-core.h4e6a38a3361b4748", - "file": "zennotes-app-core-2.81.0-core.h4e6a38a3361b4748.tgz", - "sha256": "367ea44d975bffbbc1b3003456969c6f431453d500c301fa8c923e1345fd53ca", - "integrity": "sha512-0cEPF3+zsswihP+JCcxqfij+p0ssYxPHpt58EaGDgEx8LiYFdnTP9dnu67WliUNprIdHTKAdkrwmZ6Kc7hJFCQ==", - "sourceCommit": "bfab9fdc3649934717d348bd8bd0b1b7d280e86f", + "version": "2.81.1-core.h4d33347386401068", + "file": "zennotes-app-core-2.81.1-core.h4d33347386401068.tgz", + "sha256": "2a5696f6b67d5ac2e12c9084c050cdab2c8818eec5f55b9c02f82fc0f2e5c9a1", + "integrity": "sha512-Ksdq8MeaI1cWwnHYemTVAFpm/PPyNI10D+FPHdSqcNHaMPPKQAktI06QKIF9YJk4TFiZcGhL6/jVP0weaX523w==", + "sourceCommit": "daedf423f4d1360d719c37d93b4de1be38850364", "workingTreeDirty": false, - "sourceLockSha256": "267f451b3f1b78a11ea677cd0a658c1fac91b3d0e8a736cd6618118837f3b5c1", + "sourceLockSha256": "4d1cf5531b87372ac4518556c350a39772ded709b701cf0800b75e679020e4f1", "toolchain": { "node": "v22.23.4", "typescript": "5.9.3", @@ -15,20 +15,20 @@ "dependencies": [ { "name": "@zennotes/bridge-contract", - "version": "2.81.0-boundaries.h697bb3192aa5970b", - "file": "zennotes-bridge-contract-2.81.0-boundaries.h697bb3192aa5970b.tgz", - "sha256": "534061c241f0b3055e017513cb614d10e81df0ae33a4e1e4e887dedb8e7699ee", - "integrity": "sha512-Aukkw1ZsDrTaSZ3L1fUjulNJHFpN8G/uFSeNFYpXxx5NziyL1ZYKlcO+6Mcc47qLKvHUryMhehqILZFJsXcnwQ==", - "sourceCommit": "bfab9fdc3649934717d348bd8bd0b1b7d280e86f", + "version": "2.81.1-boundaries.h35527b79ebf7355e", + "file": "zennotes-bridge-contract-2.81.1-boundaries.h35527b79ebf7355e.tgz", + "sha256": "f2019e9f294a7dcd7a2ba3e0a6916bbeb188c1785e4d12d685f4cb254e5c84b1", + "integrity": "sha512-48s1/wqVn1WwviidRDVaOwWP5l6jSvY4Pz8a4Z54vo5P0MaZthVYRDnr+ABh6/9TK4TECeNEIoc0eSLGdVsC7Q==", + "sourceCommit": "daedf423f4d1360d719c37d93b4de1be38850364", "workingTreeDirty": false }, { "name": "@zennotes/shared-domain", - "version": "2.81.0-boundaries.h697bb3192aa5970b", - "file": "zennotes-shared-domain-2.81.0-boundaries.h697bb3192aa5970b.tgz", - "sha256": "3d9d216b3941dba1842567e58a27d23a36a2f4e394c149d0e5ae6f5d1213a07f", - "integrity": "sha512-sS4/C0A/SSC8GN7cqm8wLUcBWCqenJM/BhfPFmHCKyle24EMJFbs3KPhy/4auLOErXi7Qf+wC0r+kVZmbLaciQ==", - "sourceCommit": "bfab9fdc3649934717d348bd8bd0b1b7d280e86f", + "version": "2.81.1-boundaries.h35527b79ebf7355e", + "file": "zennotes-shared-domain-2.81.1-boundaries.h35527b79ebf7355e.tgz", + "sha256": "fdc290c8ddc4b7ea3fefe75eeed6c8f8da8f295377da1cb691571152f9152356", + "integrity": "sha512-sdYdnD9Dn5xMiWIs2cAT1Bofi79LW7Xp9pms+WGZyFQ88/eBgmNbF+1k9M+RnG1fTdPHjq3O4j+NC4cndSBUZQ==", + "sourceCommit": "daedf423f4d1360d719c37d93b4de1be38850364", "workingTreeDirty": false } ] diff --git a/vendor/zennotes/zennotes-app-core-2.81.0-core.h4e6a38a3361b4748.tgz b/vendor/zennotes/zennotes-app-core-2.81.1-core.h4d33347386401068.tgz similarity index 54% rename from vendor/zennotes/zennotes-app-core-2.81.0-core.h4e6a38a3361b4748.tgz rename to vendor/zennotes/zennotes-app-core-2.81.1-core.h4d33347386401068.tgz index 575ff64..7ae9014 100644 Binary files a/vendor/zennotes/zennotes-app-core-2.81.0-core.h4e6a38a3361b4748.tgz and b/vendor/zennotes/zennotes-app-core-2.81.1-core.h4d33347386401068.tgz differ diff --git a/vendor/zennotes/zennotes-bridge-contract-2.81.0-boundaries.h697bb3192aa5970b.tgz b/vendor/zennotes/zennotes-bridge-contract-2.81.0-boundaries.h697bb3192aa5970b.tgz deleted file mode 100644 index 3f6260d..0000000 Binary files a/vendor/zennotes/zennotes-bridge-contract-2.81.0-boundaries.h697bb3192aa5970b.tgz and /dev/null differ diff --git a/vendor/zennotes/zennotes-bridge-contract-2.81.1-boundaries.h35527b79ebf7355e.tgz b/vendor/zennotes/zennotes-bridge-contract-2.81.1-boundaries.h35527b79ebf7355e.tgz new file mode 100644 index 0000000..3a0d9dc Binary files /dev/null and b/vendor/zennotes/zennotes-bridge-contract-2.81.1-boundaries.h35527b79ebf7355e.tgz differ diff --git a/vendor/zennotes/zennotes-shared-domain-2.81.0-boundaries.h697bb3192aa5970b.tgz b/vendor/zennotes/zennotes-shared-domain-2.81.1-boundaries.h35527b79ebf7355e.tgz similarity index 77% rename from vendor/zennotes/zennotes-shared-domain-2.81.0-boundaries.h697bb3192aa5970b.tgz rename to vendor/zennotes/zennotes-shared-domain-2.81.1-boundaries.h35527b79ebf7355e.tgz index 4118c00..9014dda 100644 Binary files a/vendor/zennotes/zennotes-shared-domain-2.81.0-boundaries.h697bb3192aa5970b.tgz and b/vendor/zennotes/zennotes-shared-domain-2.81.1-boundaries.h35527b79ebf7355e.tgz differ