From 77555723a759dfe42fe3f6b41854ed74b2741df0 Mon Sep 17 00:00:00 2001 From: u8array Date: Tue, 28 Jul 2026 19:06:03 +0200 Subject: [PATCH] feat(symbol): gate UL/CSA behind power-user mode with certification disclaimer --- packages/core/src/registry/symbol.ts | 4 ++ src/locales/ar.ts | 1 + src/locales/bg.ts | 1 + src/locales/cs.ts | 1 + src/locales/da.ts | 1 + src/locales/de.ts | 1 + src/locales/el.ts | 1 + src/locales/en.ts | 1 + src/locales/es.ts | 1 + src/locales/et.ts | 1 + src/locales/fa.ts | 1 + src/locales/fi.ts | 1 + src/locales/fr.ts | 1 + src/locales/he.ts | 1 + src/locales/hr.ts | 1 + src/locales/hu.ts | 1 + src/locales/it.ts | 1 + src/locales/ja.ts | 1 + src/locales/ko.ts | 1 + src/locales/lt.ts | 1 + src/locales/lv.ts | 1 + src/locales/nl.ts | 1 + src/locales/no.ts | 1 + src/locales/pl.ts | 1 + src/locales/pt.ts | 1 + src/locales/ro.ts | 1 + src/locales/sk.ts | 1 + src/locales/sl.ts | 1 + src/locales/sr.ts | 1 + src/locales/sv.ts | 1 + src/locales/tr.ts | 1 + src/locales/zh-hans.ts | 1 + src/locales/zh-hant.ts | 1 + src/registry/symbol.panel.test.tsx | 88 ++++++++++++++++++++++++++++ src/registry/symbol.panel.tsx | 19 +++++- 35 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 src/registry/symbol.panel.test.tsx diff --git a/packages/core/src/registry/symbol.ts b/packages/core/src/registry/symbol.ts index 2abd507a..4dda5303 100644 --- a/packages/core/src/registry/symbol.ts +++ b/packages/core/src/registry/symbol.ts @@ -36,6 +36,10 @@ export const DEFAULT_GS_SYMBOL_META = * for which codes round-trip cleanly. */ export const GS_SYMBOL_CODES: ReadonlySet = new Set(GS_SYMBOLS.map((s) => s.code)); +/** UL and CSA are protected certification marks, legal only on products + * certified by the issuing organisation. */ +export const CERTIFICATION_MARK_CODES: ReadonlySet = new Set(['D', 'E']); + export interface SymbolProps { /** Single-letter ZPL ^GS code that selects which symbol the printer * renders. A=®, B=©, C=™, D=UL logo, E=CSA logo. */ diff --git a/src/locales/ar.ts b/src/locales/ar.ts index 0973d75e..a1db7f27 100644 --- a/src/locales/ar.ts +++ b/src/locales/ar.ts @@ -1095,6 +1095,7 @@ const ar = { symbolTrademark: 'علامة تجارية (™)', symbolUL: 'اعتماد UL', symbolCSA: 'اعتماد CSA', + certMarkWarningFmt: '{mark} علامة اعتماد محمية. استخدمها فقط على المنتجات المعتمدة من الجهة المُصدرة.', }, upca: { content: 'المحتوى (11 رقم)', diff --git a/src/locales/bg.ts b/src/locales/bg.ts index eefbaa0e..0d42652e 100644 --- a/src/locales/bg.ts +++ b/src/locales/bg.ts @@ -1095,6 +1095,7 @@ const bg = { symbolTrademark: 'Търговска марка (™)', symbolUL: 'UL одобрение', symbolCSA: 'CSA одобрение', + certMarkWarningFmt: '{mark} е защитен сертификационен знак. Използвайте го само за продукти, сертифицирани от издаващата организация.', }, upca: { content: 'Съдържание (11 цифри)', diff --git a/src/locales/cs.ts b/src/locales/cs.ts index b3a3eaea..d439b1d2 100644 --- a/src/locales/cs.ts +++ b/src/locales/cs.ts @@ -1095,6 +1095,7 @@ const cs = { symbolTrademark: 'Ochranná známka (™)', symbolUL: 'Schválení UL', symbolCSA: 'Schválení CSA', + certMarkWarningFmt: '{mark} je chráněná certifikační značka. Používejte ji pouze u produktů certifikovaných příslušnou organizací.', }, upca: { content: 'Obsah (11 číslic)', diff --git a/src/locales/da.ts b/src/locales/da.ts index 6ee2df5b..29f60b03 100644 --- a/src/locales/da.ts +++ b/src/locales/da.ts @@ -1095,6 +1095,7 @@ const da = { symbolTrademark: 'Varemærke (™)', symbolUL: 'UL-godkendelse', symbolCSA: 'CSA-godkendelse', + certMarkWarningFmt: '{mark} er et beskyttet certificeringsmærke. Brug det kun på produkter certificeret af den udstedende organisation.', }, upca: { content: 'Indhold (11 cifre)', diff --git a/src/locales/de.ts b/src/locales/de.ts index 56052d5e..9f21cb60 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -1125,6 +1125,7 @@ const de = { symbolTrademark: 'Markenzeichen (™)', symbolUL: 'UL-Zulassung', symbolCSA: 'CSA-Zulassung', + certMarkWarningFmt: '{mark} ist ein geschütztes Zertifizierungszeichen. Nur auf Produkten verwenden, die von der jeweiligen Organisation zertifiziert sind.', }, upca: { content: 'Inhalt (11 Ziffern)', diff --git a/src/locales/el.ts b/src/locales/el.ts index b938d3bd..06f0f8b1 100644 --- a/src/locales/el.ts +++ b/src/locales/el.ts @@ -1095,6 +1095,7 @@ const el = { symbolTrademark: 'Εμπορικό σήμα (™)', symbolUL: 'Έγκριση UL', symbolCSA: 'Έγκριση CSA', + certMarkWarningFmt: 'Το {mark} είναι προστατευόμενο σήμα πιστοποίησης. Χρησιμοποιήστε το μόνο σε προϊόντα πιστοποιημένα από τον εκδίδοντα οργανισμό.', }, upca: { content: 'Περιεχόμενο (11 ψηφία)', diff --git a/src/locales/en.ts b/src/locales/en.ts index 9cb8610b..b8d45b4e 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -1125,6 +1125,7 @@ const en = { symbolTrademark: 'Trademark (™)', symbolUL: 'UL approval', symbolCSA: 'CSA approval', + certMarkWarningFmt: '{mark} is a protected certification mark. Use it only on products certified by the issuing organisation.', }, upca: { content: 'Content (11 digits)', diff --git a/src/locales/es.ts b/src/locales/es.ts index bd597225..326230bd 100644 --- a/src/locales/es.ts +++ b/src/locales/es.ts @@ -1095,6 +1095,7 @@ const es = { symbolTrademark: 'Marca registrada (™)', symbolUL: 'Aprobación UL', symbolCSA: 'Aprobación CSA', + certMarkWarningFmt: '{mark} es una marca de certificación protegida. Utilícela solo en productos certificados por la organización emisora.', }, upca: { content: 'Contenido (11 dígitos)', diff --git a/src/locales/et.ts b/src/locales/et.ts index 3e1ffa04..09fd5d28 100644 --- a/src/locales/et.ts +++ b/src/locales/et.ts @@ -1095,6 +1095,7 @@ const et = { symbolTrademark: 'Kaubamärk (™)', symbolUL: 'UL heakskiit', symbolCSA: 'CSA heakskiit', + certMarkWarningFmt: '{mark} on kaitstud sertifitseerimismärk. Kasutage seda ainult toodetel, mille on sertifitseerinud väljastav organisatsioon.', }, upca: { content: 'Sisu (11 numbrit)', diff --git a/src/locales/fa.ts b/src/locales/fa.ts index d4210946..ae24cd5e 100644 --- a/src/locales/fa.ts +++ b/src/locales/fa.ts @@ -1095,6 +1095,7 @@ const fa = { symbolTrademark: 'علامت تجاری (™)', symbolUL: 'تأیید UL', symbolCSA: 'تأیید CSA', + certMarkWarningFmt: '{mark} یک علامت گواهی حفاظت‌شده است. تنها آن را روی محصولاتی استفاده کنید که توسط سازمان صادرکننده گواهی شده‌اند.', }, upca: { content: 'محتوا (۱۱ رقم)', diff --git a/src/locales/fi.ts b/src/locales/fi.ts index e1074621..30669ddf 100644 --- a/src/locales/fi.ts +++ b/src/locales/fi.ts @@ -1095,6 +1095,7 @@ const fi = { symbolTrademark: 'Tavaramerkki (™)', symbolUL: 'UL-hyväksyntä', symbolCSA: 'CSA-hyväksyntä', + certMarkWarningFmt: '{mark} on suojattu sertifiointimerkki. Käytä sitä vain tuotteissa, jotka myöntävä organisaatio on sertifioinut.', }, upca: { content: 'Sisältö (11 numeroa)', diff --git a/src/locales/fr.ts b/src/locales/fr.ts index f483a0de..8edf004b 100644 --- a/src/locales/fr.ts +++ b/src/locales/fr.ts @@ -1095,6 +1095,7 @@ const fr = { symbolTrademark: 'Marque déposée (™)', symbolUL: 'Approbation UL', symbolCSA: 'Approbation CSA', + certMarkWarningFmt: "{mark} est une marque de certification protégée. Utilisez-la uniquement sur des produits certifiés par l'organisme émetteur.", }, upca: { content: 'Contenu (11 chiffres)', diff --git a/src/locales/he.ts b/src/locales/he.ts index 906dc294..cfa0e091 100644 --- a/src/locales/he.ts +++ b/src/locales/he.ts @@ -1095,6 +1095,7 @@ const he = { symbolTrademark: 'סימן מסחרי (™)', symbolUL: 'אישור UL', symbolCSA: 'אישור CSA', + certMarkWarningFmt: '{mark} הוא סימן הסמכה מוגן. יש להשתמש בו רק במוצרים המוסמכים על ידי הגוף המנפיק.', }, upca: { content: 'תוכן (11 ספרות)', diff --git a/src/locales/hr.ts b/src/locales/hr.ts index 254f74b0..bd379477 100644 --- a/src/locales/hr.ts +++ b/src/locales/hr.ts @@ -1095,6 +1095,7 @@ const hr = { symbolTrademark: 'Zaštitni znak (™)', symbolUL: 'UL odobrenje', symbolCSA: 'CSA odobrenje', + certMarkWarningFmt: '{mark} je zaštićena certifikacijska oznaka. Koristite je samo na proizvodima koje je certificirala izdavačka organizacija.', }, upca: { content: 'Sadržaj (11 znamenki)', diff --git a/src/locales/hu.ts b/src/locales/hu.ts index 90991f2f..ff2a5bea 100644 --- a/src/locales/hu.ts +++ b/src/locales/hu.ts @@ -1095,6 +1095,7 @@ const hu = { symbolTrademark: 'Védjegy (™)', symbolUL: 'UL-jóváhagyás', symbolCSA: 'CSA-jóváhagyás', + certMarkWarningFmt: 'A(z) {mark} védett tanúsítási jelölés. Csak a kibocsátó szervezet által tanúsított termékeken használja.', }, upca: { content: 'Tartalom (11 számjegy)', diff --git a/src/locales/it.ts b/src/locales/it.ts index 81e057c2..9d2040fd 100644 --- a/src/locales/it.ts +++ b/src/locales/it.ts @@ -1095,6 +1095,7 @@ const it = { symbolTrademark: 'Marchio registrato (™)', symbolUL: 'Approvazione UL', symbolCSA: 'Approvazione CSA', + certMarkWarningFmt: "{mark} è un marchio di certificazione protetto. Utilizzarlo solo su prodotti certificati dall'ente emittente.", }, upca: { content: 'Contenuto (11 cifre)', diff --git a/src/locales/ja.ts b/src/locales/ja.ts index 5598d2e0..5e04fa73 100644 --- a/src/locales/ja.ts +++ b/src/locales/ja.ts @@ -1095,6 +1095,7 @@ const ja = { symbolTrademark: '商標 (™)', symbolUL: 'UL認証', symbolCSA: 'CSA認証', + certMarkWarningFmt: '{mark}は保護された認証マークです。発行団体が認証した製品にのみ使用してください。', }, upca: { content: '内容(11桁)', diff --git a/src/locales/ko.ts b/src/locales/ko.ts index 212dc5f8..f5dbf9bf 100644 --- a/src/locales/ko.ts +++ b/src/locales/ko.ts @@ -1095,6 +1095,7 @@ const ko = { symbolTrademark: '상표 (™)', symbolUL: 'UL 승인', symbolCSA: 'CSA 승인', + certMarkWarningFmt: '{mark}는 보호되는 인증 마크입니다. 발행 기관이 인증한 제품에만 사용하세요.', }, upca: { content: '내용 (11자리)', diff --git a/src/locales/lt.ts b/src/locales/lt.ts index 423de8af..7fccff43 100644 --- a/src/locales/lt.ts +++ b/src/locales/lt.ts @@ -1095,6 +1095,7 @@ const lt = { symbolTrademark: 'Prekės ženklas (™)', symbolUL: 'UL patvirtinimas', symbolCSA: 'CSA patvirtinimas', + certMarkWarningFmt: '{mark} yra saugomas sertifikavimo ženklas. Naudokite jį tik produktams, kuriuos sertifikavo juos išduodanti organizacija.', }, upca: { content: 'Turinys (11 skaitmenų)', diff --git a/src/locales/lv.ts b/src/locales/lv.ts index a60c9624..b917b758 100644 --- a/src/locales/lv.ts +++ b/src/locales/lv.ts @@ -1095,6 +1095,7 @@ const lv = { symbolTrademark: 'Preču zīme (™)', symbolUL: 'UL apstiprinājums', symbolCSA: 'CSA apstiprinājums', + certMarkWarningFmt: '{mark} ir aizsargāta sertifikācijas zīme. Izmantojiet to tikai produktiem, kurus sertificējusi izdevēja organizācija.', }, upca: { content: 'Saturs (11 cipari)', diff --git a/src/locales/nl.ts b/src/locales/nl.ts index 7959ee04..024011de 100644 --- a/src/locales/nl.ts +++ b/src/locales/nl.ts @@ -1095,6 +1095,7 @@ const nl = { symbolTrademark: 'Handelsmerk (™)', symbolUL: 'UL-goedkeuring', symbolCSA: 'CSA-goedkeuring', + certMarkWarningFmt: '{mark} is een beschermd certificeringsmerk. Gebruik het alleen op producten die door de uitgevende organisatie zijn gecertificeerd.', }, upca: { content: 'Inhoud (11 cijfers)', diff --git a/src/locales/no.ts b/src/locales/no.ts index 542e1eb3..dc58cb09 100644 --- a/src/locales/no.ts +++ b/src/locales/no.ts @@ -1095,6 +1095,7 @@ const no = { symbolTrademark: 'Varemerke (™)', symbolUL: 'UL-godkjenning', symbolCSA: 'CSA-godkjenning', + certMarkWarningFmt: '{mark} er et beskyttet sertifiseringsmerke. Bruk det kun på produkter sertifisert av den utstedende organisasjonen.', }, upca: { content: 'Innhold (11 siffer)', diff --git a/src/locales/pl.ts b/src/locales/pl.ts index 77056022..97162734 100644 --- a/src/locales/pl.ts +++ b/src/locales/pl.ts @@ -1095,6 +1095,7 @@ const pl = { symbolTrademark: 'Znak towarowy (™)', symbolUL: 'Aprobata UL', symbolCSA: 'Aprobata CSA', + certMarkWarningFmt: '{mark} to chroniony znak certyfikacji. Używaj go wyłącznie na produktach certyfikowanych przez wydającą je organizację.', }, upca: { content: 'Zawartość (11 cyfr)', diff --git a/src/locales/pt.ts b/src/locales/pt.ts index 00191b48..b76e6047 100644 --- a/src/locales/pt.ts +++ b/src/locales/pt.ts @@ -1095,6 +1095,7 @@ const pt = { symbolTrademark: 'Marca registrada (™)', symbolUL: 'Aprovação UL', symbolCSA: 'Aprovação CSA', + certMarkWarningFmt: '{mark} é uma marca de certificação protegida. Utilize-a apenas em produtos certificados pela organização emissora.', }, upca: { content: 'Conteúdo (11 dígitos)', diff --git a/src/locales/ro.ts b/src/locales/ro.ts index 8786c3c7..d886f4ff 100644 --- a/src/locales/ro.ts +++ b/src/locales/ro.ts @@ -1095,6 +1095,7 @@ const ro = { symbolTrademark: 'Marcă comercială (™)', symbolUL: 'Aprobare UL', symbolCSA: 'Aprobare CSA', + certMarkWarningFmt: '{mark} este o marcă de certificare protejată. Utilizați-o doar pe produse certificate de organizația emitentă.', }, upca: { content: 'Conținut (11 cifre)', diff --git a/src/locales/sk.ts b/src/locales/sk.ts index d64f5b59..365e3bc3 100644 --- a/src/locales/sk.ts +++ b/src/locales/sk.ts @@ -1095,6 +1095,7 @@ const sk = { symbolTrademark: 'Ochranná známka (™)', symbolUL: 'Schválenie UL', symbolCSA: 'Schválenie CSA', + certMarkWarningFmt: '{mark} je chránená certifikačná značka. Používajte ju iba na produktoch certifikovaných vydávajúcou organizáciou.', }, upca: { content: 'Obsah (11 číslic)', diff --git a/src/locales/sl.ts b/src/locales/sl.ts index 98b976c3..ceb3d4e7 100644 --- a/src/locales/sl.ts +++ b/src/locales/sl.ts @@ -1095,6 +1095,7 @@ const sl = { symbolTrademark: 'Blagovna znamka (™)', symbolUL: 'UL odobritev', symbolCSA: 'CSA odobritev', + certMarkWarningFmt: '{mark} je zaščitena certifikacijska znamka. Uporabljajte jo samo na izdelkih, ki jih je certificirala izdajateljska organizacija.', }, upca: { content: 'Vsebina (11 števk)', diff --git a/src/locales/sr.ts b/src/locales/sr.ts index 812634a5..7d458418 100644 --- a/src/locales/sr.ts +++ b/src/locales/sr.ts @@ -1095,6 +1095,7 @@ const sr = { symbolTrademark: 'Заштитни знак (™)', symbolUL: 'UL одобрење', symbolCSA: 'CSA одобрење', + certMarkWarningFmt: '{mark} је заштићена сертификациона ознака. Користите је само на производима које је сертификовала издавачка организација.', }, upca: { content: 'Садржај (11 цифара)', diff --git a/src/locales/sv.ts b/src/locales/sv.ts index 8a67fe1f..e08d428f 100644 --- a/src/locales/sv.ts +++ b/src/locales/sv.ts @@ -1095,6 +1095,7 @@ const sv = { symbolTrademark: 'Varumärke (™)', symbolUL: 'UL-godkännande', symbolCSA: 'CSA-godkännande', + certMarkWarningFmt: '{mark} är ett skyddat certifieringsmärke. Använd det endast på produkter certifierade av den utfärdande organisationen.', }, upca: { content: 'Innehåll (11 siffror)', diff --git a/src/locales/tr.ts b/src/locales/tr.ts index 8bf83ecb..f4725daf 100644 --- a/src/locales/tr.ts +++ b/src/locales/tr.ts @@ -1095,6 +1095,7 @@ const tr = { symbolTrademark: 'Ticari marka (™)', symbolUL: 'UL onayı', symbolCSA: 'CSA onayı', + certMarkWarningFmt: '{mark} korumalı bir sertifikasyon işaretidir. Yalnızca veren kuruluş tarafından sertifikalandırılmış ürünlerde kullanın.', }, upca: { content: 'İçerik (11 hane)', diff --git a/src/locales/zh-hans.ts b/src/locales/zh-hans.ts index 6c002bd0..26bb1415 100644 --- a/src/locales/zh-hans.ts +++ b/src/locales/zh-hans.ts @@ -1095,6 +1095,7 @@ const zhHans = { symbolTrademark: '商标 (™)', symbolUL: 'UL 认证', symbolCSA: 'CSA 认证', + certMarkWarningFmt: '{mark} 是受保护的认证标志。仅可用于经发证机构认证的产品。', }, upca: { content: '内容(11位)', diff --git a/src/locales/zh-hant.ts b/src/locales/zh-hant.ts index e2b638a7..c0e39c08 100644 --- a/src/locales/zh-hant.ts +++ b/src/locales/zh-hant.ts @@ -1095,6 +1095,7 @@ const zhHant = { symbolTrademark: '商標 (™)', symbolUL: 'UL 認證', symbolCSA: 'CSA 認證', + certMarkWarningFmt: '{mark} 是受保護的認證標誌。僅可用於經發證機構認證的產品。', }, upca: { content: '內容(11位)', diff --git a/src/registry/symbol.panel.test.tsx b/src/registry/symbol.panel.test.tsx new file mode 100644 index 00000000..3ba48585 --- /dev/null +++ b/src/registry/symbol.panel.test.tsx @@ -0,0 +1,88 @@ +// @vitest-environment jsdom +import { describe, it, expect, afterEach, beforeEach } from "vitest"; +import { render, cleanup, act } from "@testing-library/react"; +import { symbolPanel } from "./symbol.panel"; +import { useLabelStore } from "../store/labelStore"; +import { fallbackTranslations as en } from "../locales"; +import type { SymbolProps } from "@zplab/core/registry/symbol"; +import type { LabelObjectBase } from "@zplab/core/types/LabelObject"; + +afterEach(cleanup); +beforeEach(() => { + act(() => { + useLabelStore.setState({ showZplCommands: false } as never); + }); +}); + +const makeObj = (symbol: SymbolProps["symbol"]): LabelObjectBase & { props: SymbolProps } => ({ + id: "sym-1", + type: "symbol", + x: 0, + y: 0, + rotation: 0, + props: { symbol, height: 40, width: 40, rotation: "N" }, +}); + +const Panel = symbolPanel.PropertiesPanel; + +describe("symbol panel certification-mark gate", () => { + it("hides UL/CSA options without power-user mode", () => { + const { getByRole, getAllByRole, queryByRole } = render( + undefined} />, + ); + // Options only mount once the listbox is open; asserting against the + // closed trigger would pass even with the gate removed. + act(() => { + getByRole("button", { name: en.registry.symbol.symbol }).click(); + }); + expect(getAllByRole("option").length).toBeGreaterThan(0); + expect(queryByRole("option", { name: /UL/ })).toBeNull(); + expect(queryByRole("option", { name: /CSA/ })).toBeNull(); + }); + + it("offers UL/CSA in power-user mode", () => { + act(() => { + useLabelStore.setState({ showZplCommands: true } as never); + }); + const { getByRole, getByText } = render( + undefined} />, + ); + act(() => { + getByRole("button", { name: en.registry.symbol.symbol }).click(); + }); + expect(getByText(new RegExp(en.registry.symbol.symbolUL))).toBeTruthy(); + expect(getByText(new RegExp(en.registry.symbol.symbolCSA))).toBeTruthy(); + }); + + it("keeps a carried UL selectable without power-user mode and shows the disclaimer", () => { + const { getByRole, getByText, getAllByText, queryByText } = render( + undefined} />, + ); + expect(getByText(en.registry.symbol.certMarkWarningFmt.replace("{mark}", "UL"))).toBeTruthy(); + act(() => { + getByRole("button", { name: en.registry.symbol.symbol }).click(); + }); + // Current value stays listed (trigger + option); CSA stays hidden. + expect(getAllByText(new RegExp(en.registry.symbol.symbolUL)).length).toBeGreaterThan(1); + expect(queryByText(new RegExp(en.registry.symbol.symbolCSA))).toBeNull(); + }); + + it("mirrors the carried-value exception for CSA", () => { + const { getByRole, getByText, getAllByText, queryByText } = render( + undefined} />, + ); + expect(getByText(en.registry.symbol.certMarkWarningFmt.replace("{mark}", "CSA"))).toBeTruthy(); + act(() => { + getByRole("button", { name: en.registry.symbol.symbol }).click(); + }); + expect(getAllByText(new RegExp(en.registry.symbol.symbolCSA)).length).toBeGreaterThan(1); + expect(queryByText(new RegExp(en.registry.symbol.symbolUL))).toBeNull(); + }); + + it("shows no disclaimer for plain trademark symbols", () => { + const { queryByText } = render( + undefined} />, + ); + expect(queryByText(/certification mark/)).toBeNull(); + }); +}); diff --git a/src/registry/symbol.panel.tsx b/src/registry/symbol.panel.tsx index 1e94ddfd..a0dd088f 100644 --- a/src/registry/symbol.panel.tsx +++ b/src/registry/symbol.panel.tsx @@ -1,17 +1,24 @@ import type { ObjectTypeUi } from './panelTypes'; import { useT } from '../hooks/useT'; +import { useLabelStore } from '../store/labelStore'; import { UnitNumberInput } from '../components/Properties/UnitNumberInput'; import { RotationSelect } from '../components/Properties/RotationSelect'; import { SectionCard } from '../components/Properties/SectionCard'; import { FieldLabel } from '../components/Properties/ZplCmd'; import { Select } from '../components/ui/Select'; import { fieldGridCols, fieldGridCell } from '../components/ui/formStyles'; -import { type SymbolProps, type SymbolCode, GS_SYMBOLS } from '@zplab/core/registry/symbol'; +import { type SymbolProps, type SymbolCode, DEFAULT_GS_SYMBOL_META, GS_SYMBOLS, CERTIFICATION_MARK_CODES } from '@zplab/core/registry/symbol'; export const symbolPanel: ObjectTypeUi = { PropertiesPanel: ({ obj, onChange }) => { const t = useT(); const p = obj.props; + const showZpl = useLabelStore((s) => s.showZplCommands); + // Certification marks are power-user only, but an object already carrying + // one (import, or toggled mode) must keep its current option visible. + const symbols = GS_SYMBOLS.filter( + (s) => showZpl || !CERTIFICATION_MARK_CODES.has(s.code) || s.code === p.symbol, + ); return (
@@ -20,11 +27,19 @@ export const symbolPanel: ObjectTypeUi = { value={p.symbol} onChange={(symbol) => onChange({ symbol })} aria-label={t.registry.symbol.symbol} - groups={[{ options: GS_SYMBOLS.map((s) => ({ + groups={[{ options: symbols.map((s) => ({ value: s.code, label: `${s.glyph} ${t.registry.symbol[s.label as keyof typeof t.registry.symbol]}`, })) }]} /> + {CERTIFICATION_MARK_CODES.has(p.symbol) && ( +

+ {t.registry.symbol.certMarkWarningFmt.replace( + '{mark}', + (GS_SYMBOLS.find((s) => s.code === p.symbol) ?? DEFAULT_GS_SYMBOL_META).glyph, + )} +

+ )}