@smartsoft001-mobilems/claude-plugins 2.129.0 → 2.130.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartsoft001-mobilems/claude-plugins",
3
- "version": "2.129.0",
3
+ "version": "2.130.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "mobilems",
3
3
  "description": "MobilEMS-specific Claude Code skills (MuzaCMS / MobileMS indexer API)",
4
- "version": "2.129.0"
4
+ "version": "2.130.0"
5
5
  }
@@ -35,21 +35,22 @@ list — re-implementing framework code is a defect, not a shortcut:
35
35
  2. [`packages/objects/README.md`](https://github.com/smartsoft001/mobilems-framework/blob/main/packages/objects/README.md) — this module's package catalog
36
36
  3. `libs/shared/angular/README.md` — the app's own shared lib (built by `mobilems-project-init`)
37
37
 
38
- | Do not hand-roll | Use |
39
- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
40
- | a masonry grid (`new Masonry(...)`, per-page masonry JS/CSS) | `<smart-mobilems-masonry-grid>` (`MasonryGridComponent`) with a `#masonryContentTpl`; the `Masonry` provider in step 3 only feeds it |
41
- | filter state / hand-built `query` arrays | `FiltersBaseComponent<MsObject>` + its `FiltersContext` accessors (`searchText`, `keywords`, `page`, `sort`, `onlyImage`, …) |
42
- | list page logic (first read, persistence, SSR read, read guard, load-more, masonry lifecycle, list SEO) | `ObjectsCatalogBaseComponent` (`pages/list` extends it; the app keeps its own markup and `sortOptions` over `isNewType`) |
43
- | detail page logic (SSR SEO, scroll, visit counter, retry, opt-in related / related collections) | `ObjectDetailsBaseComponent` (extends `ObjectsItemComponent`; `pages/item` extends it, `related` and `relatedCollections` are opt-in via the constructor options) |
44
- | object detail field helpers (title, tags, inventory, bibliography, description, related articles, ask-about link) | the `objectTitle`, `tagValues`, `inventoryValues`, `bibliography`, `descriptionHtml`, `relatedArticles`, `askAboutObjectHref` tools |
45
- | gallery / media lists | `ObjectMediaService` |
46
- | visit counter, related objects, collection / archaeological dictionaries | `ObjectsDataService` (extends `ObjectsService`) |
47
- | filter bar (sort / limit, chips, dictionary toggles, year range, theme tags) | `ObjectsFiltersBarBaseComponent` (`components/filters-top` extends it; the app keeps its markup; the cycle theme tags are opt-in with `cycleTags: true`, otherwise no `dictionary/Cycle` request) |
48
- | search panel (phrase, tags, boolean filters) - Podlasie-style museums only | `ObjectsSearchPanelBaseComponent` (S/T-style museums have no search panel: they use the filters bar only) |
49
- | advanced filters panel - Podlasie-style museums only | `ObjectsAdvancedFiltersBaseComponent` (the field config `IObjectsAdvancedFilterField[]` stays in the app, the framework exports only the types; S/T-style museums skip it) |
50
- | share results link | `ObjectsShareResultsBaseComponent` (extends the shared `ShareLinkBaseComponent`; set `objectsShareResultsListPath` for another list) |
51
- | sort / limit options, sort keys, results URL | `OBJECTS_SORT_OPTIONS`, `OBJECTS_NEW_TYPE_SORT_OPTIONS`, `OBJECTS_LIMIT_OPTIONS`, `objectsSortKey`, `objectsSortFromKey`, `buildObjectsResultsUrl` |
52
- | media URLs, meta/OG tags, filter dictionaries, modals, WCAG | `FileUrlService`, `SeoService`/`MetaService`, `DictionaryService`, `ModalService`, `WcagService` |
38
+ | Do not hand-roll | Use |
39
+ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
40
+ | a masonry grid (`new Masonry(...)`, per-page masonry JS/CSS) | `<smart-mobilems-masonry-grid>` (`MasonryGridComponent`) with a `#masonryContentTpl`; the `Masonry` provider in step 3 only feeds it |
41
+ | filter state / hand-built `query` arrays | `FiltersBaseComponent<MsObject>` + its `FiltersContext` accessors (`searchText`, `keywords`, `page`, `sort`, `onlyImage`, …) |
42
+ | list page logic (first read, persistence, SSR read, read guard, load-more, masonry lifecycle, list SEO) | `ObjectsCatalogBaseComponent` (`pages/list` extends it; the app keeps its own markup and `sortOptions` over `isNewType`) |
43
+ | detail page logic (SSR SEO, scroll, visit counter, retry, opt-in related / related collections) | `ObjectDetailsBaseComponent` (extends `ObjectsItemComponent`; `pages/item` extends it, `related` and `relatedCollections` are opt-in via the constructor options) |
44
+ | object detail field helpers (title, tags, inventory, bibliography, description, related articles, ask-about link) | the `objectTitle`, `tagValues`, `inventoryValues`, `bibliography`, `descriptionHtml`, `relatedArticles`, `askAboutObjectHref` tools |
45
+ | gallery / media lists | `ObjectMediaService` |
46
+ | visit counter, related objects, collection / archaeological dictionaries | `ObjectsDataService` (extends `ObjectsService`) |
47
+ | media tabs (images aside): map, audio, audio description, documents, animation, video, virtual walk, 3D model, download button, `media-sections` | `components/tabs/*` extend the `Object…TabBaseComponent` bases (`ObjectMapTabBaseComponent`, `ObjectAudioTabBaseComponent`, `ObjectAudioDescriptionTabBaseComponent`, `ObjectDocumentsTabBaseComponent`, `ObjectAnimationTabBaseComponent`, `ObjectVideoTabBaseComponent`, `ObjectVirtualWalkTabBaseComponent`, `ObjectModel3dTabBaseComponent`, `ObjectDownloadButtonBaseComponent`, `ObjectMediaSectionsBaseComponent`) from `objects-shell-angular`: logic in the framework, `selector`/`template`/`styles`/`imports` in the app. The 3D tab implements `loadModel3dLibrary()` as `import('online-3d-viewer')`; `playableOnly` (audio) and `loadableOnly` (3D) default to `true` (Podlasie), pass `false` to keep the unfiltered list |
48
+ | filter bar (sort / limit, chips, dictionary toggles, year range, theme tags) | `ObjectsFiltersBarBaseComponent` (`components/filters-top` extends it; the app keeps its markup; the cycle theme tags are opt-in with `cycleTags: true`, otherwise no `dictionary/Cycle` request) |
49
+ | search panel (phrase, tags, boolean filters) - Podlasie-style museums only | `ObjectsSearchPanelBaseComponent` (S/T-style museums have no search panel: they use the filters bar only) |
50
+ | advanced filters panel - Podlasie-style museums only | `ObjectsAdvancedFiltersBaseComponent` (the field config `IObjectsAdvancedFilterField[]` stays in the app, the framework exports only the types; S/T-style museums skip it) |
51
+ | share results link | `ObjectsShareResultsBaseComponent` (extends the shared `ShareLinkBaseComponent`; set `objectsShareResultsListPath` for another list) |
52
+ | sort / limit options, sort keys, results URL | `OBJECTS_SORT_OPTIONS`, `OBJECTS_NEW_TYPE_SORT_OPTIONS`, `OBJECTS_LIMIT_OPTIONS`, `objectsSortKey`, `objectsSortFromKey`, `buildObjectsResultsUrl` |
53
+ | media URLs, meta/OG tags, filter dictionaries, modals, WCAG | `FileUrlService`, `SeoService`/`MetaService`, `DictionaryService`, `ModalService`, `WcagService` |
53
54
 
54
55
  Anything the framework genuinely lacks goes into `libs/shared/angular` **once** (and into its
55
56
  README) — never a per-module copy. `scripts/verify-module.sh` fails the run on hand-rolled masonry.
@@ -80,7 +81,7 @@ tab, the grid/list item cards and the object gallery widget.
80
81
 
81
82
  1. **npm deps** — add `@smartsoft001-mobilems/objects-domain`, `@smartsoft001-mobilems/objects-shell-angular`,
82
83
  `@smartsoft001-mobilems/objects-shell-dtos` (match the installed mobilems line) and
83
- `online-3d-viewer` (the 3D tab; `leaflet`/`openseadragon`/`swiper` are already foundation deps).
84
+ `online-3d-viewer` (the 3D tab, loaded only through `loadModel3dLibrary()`; `leaflet`/`openseadragon`/`swiper` are already foundation deps).
84
85
  Resolve versions at run time; do not `npm install` unless asked.
85
86
  2. **Library** — scaffold `libs/museum-objects` with this package's Nx generator (deterministic — do
86
87
  NOT copy files by hand when the generator is available):
@@ -21,7 +21,7 @@ libs/museum-objects/
21
21
  ├── objects.module.ts # MuseumObjectsModule (references/module-and-routes.md)
22
22
  ├── objects.routes.ts
23
23
  ├── components/ # description, filters-top (extends ObjectsFiltersBarBaseComponent), high-def-request-modal,
24
- │ # menu, objects-searchbar (only where the app renders the panel search), tabs/*;
24
+ │ # menu, objects-searchbar (only where the app renders the panel search), tabs/* (thin classes on the framework bases);
25
25
  │ # no filter-input (it comes from the shared lib); Podlasie-style apps also keep
26
26
  │ # objects-search-panel and objects-advanced-filters (extend the framework bases)
27
27
  ├── pages/ # list (ListComponent), item (ItemComponent) + index
@@ -73,6 +73,8 @@ export class MuseumObject extends MsObject {
73
73
  - **jest `__mocks__`** — keep the `src/__mocks__/@smartsoft001-mobilems/*` stubs from the reference;
74
74
  they let the shell unit-test without the real feature packages.
75
75
 
76
- The tabs (`tabs/*`) include the 3D model tab, which uses `online-3d-viewer` — that's why this skill
76
+ The tabs (`tabs/*`) are thin classes: each extends its `Object…TabBaseComponent` from
77
+ `@smartsoft001-mobilems/objects-shell-angular` (logic) and keeps only selector, template, styles and imports. The 3D
78
+ model tab implements `loadModel3dLibrary()` with `import('online-3d-viewer')` — that's why this skill
77
79
  adds that dep. The map tab uses `leaflet`, images use `openseadragon`/`swiper` — already foundation
78
80
  deps.
@@ -167,6 +167,39 @@ for pair in "objects-search-panel.component.ts:ObjectsSearchPanelBaseComponent"
167
167
  done
168
168
  done
169
169
 
170
+ # 9. media tabs are thin classes on the framework bases; no hand-rolled fullscreen / download plumbing
171
+ TABDIR="$LIBDIR/components/tabs"
172
+ if [ -d "$TABDIR" ]; then
173
+ for f in "$TABDIR"/*.component.ts; do
174
+ [ -f "$f" ] || continue
175
+ case "$(basename "$f")" in
176
+ *.spec.ts) continue ;;
177
+ audio-description-tab.component.ts) base=ObjectAudioDescriptionTabBaseComponent ;;
178
+ audio-tab.component.ts) base=ObjectAudioTabBaseComponent ;;
179
+ animation-tab.component.ts) base=ObjectAnimationTabBaseComponent ;;
180
+ documents-tab.component.ts) base=ObjectDocumentsTabBaseComponent ;;
181
+ map-tab.component.ts) base=ObjectMapTabBaseComponent ;;
182
+ model-3d-tab.component.ts) base=ObjectModel3dTabBaseComponent ;;
183
+ video-tab.component.ts) base=ObjectVideoTabBaseComponent ;;
184
+ virtual-walk-tab.component.ts) base=ObjectVirtualWalkTabBaseComponent ;;
185
+ download-button.component.ts) base=ObjectDownloadButtonBaseComponent ;;
186
+ media-sections.component.ts) base=ObjectMediaSectionsBaseComponent ;;
187
+ *) continue ;;
188
+ esac
189
+ if grep -qE "extends[[:space:]]+$base" "$f"; then
190
+ pass "$(basename "$f") extends $base"
191
+ else
192
+ bad "$(basename "$f") does not extend $base - tab logic belongs to the framework base ($f)"
193
+ fi
194
+ done
195
+ fi
196
+ if [ -d "$TABDIR" ] && grep -rqE --include='*.ts' --exclude='*.spec.ts' "fullscreenchange|createObjectURL" "$TABDIR" 2>/dev/null; then
197
+ bad "tabs contain fullscreenchange or createObjectURL - fullscreen / download logic belongs to the framework bases:"
198
+ grep -rnE --include='*.ts' --exclude='*.spec.ts' "fullscreenchange|createObjectURL" "$TABDIR" >&2 || true
199
+ else
200
+ pass "no hand-rolled fullscreen or blob-download plumbing in the tabs"
201
+ fi
202
+
170
203
  echo "== Translations (REF_ROOT=${REF_ROOT:-unset}) =="
171
204
  # Groups: present in pl+en, no dead references, complete vs the reference repo
172
205
  # (export REF_ROOT=<reference-repo-root> to enable the completeness diff).