@c-code/c-code-fw 1.2.6 → 2.0.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/README.md +118 -0
- package/fesm2022/c-code-c-code-fw-ui.mjs +1260 -0
- package/fesm2022/c-code-c-code-fw-ui.mjs.map +1 -0
- package/package.json +9 -2
- package/ui/index.d.ts +5 -0
- package/ui/lib/components/button/button.component.d.ts +24 -0
- package/ui/lib/components/category-menu/category-menu.component.d.ts +28 -0
- package/ui/lib/components/faq/faq.component.d.ts +23 -0
- package/ui/lib/components/faq-item/faq-item.component.d.ts +21 -0
- package/ui/lib/components/gallery/gallery.component.d.ts +31 -0
- package/ui/lib/components/info-item/info-item.component.d.ts +26 -0
- package/ui/lib/components/lightbox/lightbox.component.d.ts +41 -0
- package/ui/lib/components/notice/notice.component.d.ts +17 -0
- package/ui/lib/components/page-banner/page-banner.component.d.ts +29 -0
- package/ui/lib/components/plan-card/plan-card.component.d.ts +46 -0
- package/ui/lib/components/plan-catalog/plan-catalog.component.d.ts +102 -0
- package/ui/lib/components/plan-details/plan-details.component.d.ts +59 -0
- package/ui/lib/components/plan-filter-form/plan-filter-form.component.d.ts +38 -0
- package/ui/lib/components/promo-modal/promo-modal.component.d.ts +56 -0
- package/ui/lib/components/search-box/search-box.component.d.ts +23 -0
- package/ui/lib/components/section-heading/section-heading.component.d.ts +34 -0
- package/ui/lib/components/social-links/social-links.component.d.ts +21 -0
- package/ui/lib/components/whatsapp-button/whatsapp-button.component.d.ts +29 -0
- package/ui/lib/models/plan.models.d.ts +50 -0
- package/ui/lib/models/ui.models.d.ts +24 -0
- package/ui/lib/services/plan-catalog.service.d.ts +43 -0
- package/ui/lib/services/seo.service.d.ts +39 -0
- package/ui/lib/utils/plan.utils.d.ts +16 -0
- package/ui/lib/utils/text.utils.d.ts +25 -0
- package/ui/public-api.d.ts +24 -0
- package/ui/theme/component-base.css +136 -0
- package/ui/theme/tokens.css +111 -0
package/README.md
CHANGED
|
@@ -190,6 +190,124 @@ The `ScreenWidthEventService` uses Tailwind CSS breakpoints for responsive behav
|
|
|
190
190
|
|
|
191
191
|
---
|
|
192
192
|
|
|
193
|
+
## UI components: `@c-code/c-code-fw/ui`
|
|
194
|
+
|
|
195
|
+
Presentational components for spa and catalog sites: standalone Angular 19 components with signal inputs and OnPush, safe for SSR and prerendering. Styling is plain CSS driven by CSS variables, so a site needs no Tailwind configuration to use them.
|
|
196
|
+
|
|
197
|
+
### Who owns what
|
|
198
|
+
|
|
199
|
+
- **The library owns structure:** type scale, spacing, radii, shadows, control heights, motion and layers. Each component also exposes props to choose how it looks (`variant`, `tone`, `size`, `layout`, `appearance`, `italic`…).
|
|
200
|
+
- **The site owns identity:** colors and fonts. The library ships **no palette**. Components read a contract of semantic roles that each site maps from its own variables. Without a site theme, components render in neutral grays.
|
|
201
|
+
|
|
202
|
+
### Setup
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
// app.config.ts
|
|
206
|
+
import { provideHttpClient, withFetch } from '@angular/common/http';
|
|
207
|
+
import { providePlanCatalog, provideSeo } from '@c-code/c-code-fw/ui';
|
|
208
|
+
|
|
209
|
+
export const appConfig: ApplicationConfig = {
|
|
210
|
+
providers: [
|
|
211
|
+
provideHttpClient(withFetch()),
|
|
212
|
+
providePlanCatalog(), // reads assets/data/{plans,additionals,priceRanges}.json
|
|
213
|
+
provideSeo({ siteUrl: 'https://www.example.com', defaultImage: '/assets/images/og.jpeg' }),
|
|
214
|
+
],
|
|
215
|
+
};
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Theme the site in `styles.css`, using any names for your brand variables:
|
|
219
|
+
|
|
220
|
+
```css
|
|
221
|
+
:root {
|
|
222
|
+
/* Brand, owned by the site */
|
|
223
|
+
--laurel-green: #4c6b4a;
|
|
224
|
+
--laurel-gold: #ceab5d;
|
|
225
|
+
|
|
226
|
+
/* Roles read by the components */
|
|
227
|
+
--cc-heading: var(--laurel-green);
|
|
228
|
+
--cc-text: var(--laurel-green);
|
|
229
|
+
--cc-accent: var(--laurel-gold);
|
|
230
|
+
--cc-on-accent: #022b04;
|
|
231
|
+
--cc-font-heading: 'El Messiri', serif;
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Optionally add `node_modules/@c-code/c-code-fw/ui/theme/tokens.css` to `angular.json` → `styles` to use the same scales in the site's own markup, for example by mapping Tailwind's `fontSize` to `var(--cc-text-*)`.
|
|
236
|
+
|
|
237
|
+
### Color and font roles (set by the site)
|
|
238
|
+
|
|
239
|
+
| Role | Used for | Neutral default |
|
|
240
|
+
|---|---|---|
|
|
241
|
+
| `--cc-canvas` | page background behind components, input fields | `#ffffff` |
|
|
242
|
+
| `--cc-surface` | cards, panels, sidebar | `#f5f5f4` |
|
|
243
|
+
| `--cc-surface-alt` | alternative bands, image placeholders | `#fafaf9` |
|
|
244
|
+
| `--cc-text` | body text | `#292524` |
|
|
245
|
+
| `--cc-text-muted` | counters, metadata | `--cc-text` at 72% |
|
|
246
|
+
| `--cc-heading` | titles | `#1c1917` |
|
|
247
|
+
| `--cc-accent` / `--cc-accent-hover` | primary buttons, active items | `#1c1917` / `#44403c` |
|
|
248
|
+
| `--cc-accent-text` | accent used as text (needs 4.5:1) | `--cc-heading` |
|
|
249
|
+
| `--cc-on-accent` | text on the accent (needs 4.5:1) | `#ffffff` |
|
|
250
|
+
| `--cc-inverse` / `--cc-inverse-hover` / `--cc-on-inverse` | dark blocks: price badge, dark buttons | `#1c1917` / `#000` / `#fff` |
|
|
251
|
+
| `--cc-border` / `--cc-border-strong` | dividers / input borders (3:1) | `#d6d3d1` / `#78716c` |
|
|
252
|
+
| `--cc-focus-ring` | keyboard focus | `--cc-heading` |
|
|
253
|
+
| `--cc-overlay` | modal and lightbox backdrop | `rgb(0 0 0 / 0.7)` |
|
|
254
|
+
| `--cc-danger`, `--cc-danger-surface`, `--cc-on-danger-surface` | warnings (`cc-notice tone="warning"`) | reds |
|
|
255
|
+
| `--cc-whatsapp`, `--cc-whatsapp-hover`, `--cc-on-whatsapp` | WhatsApp buttons | WhatsApp green |
|
|
256
|
+
| `--cc-font-body`, `--cc-font-heading` | font families | `inherit` |
|
|
257
|
+
| `--cc-heading-style`, `--cc-heading-transform`, `--cc-heading-tracking` | italic, uppercase, letter spacing of titles | `normal`, `none`, `normal` |
|
|
258
|
+
|
|
259
|
+
### Structure tokens (owned by the library)
|
|
260
|
+
|
|
261
|
+
All of them can be overridden, but they already have values: `--cc-text-xs…4xl`, `--cc-leading-*`, `--cc-weight-*`, `--cc-space-1…24` (4px base, same steps as Tailwind), `--cc-radius`, `--cc-radius-sm|md|lg|pill`, `--cc-shadow-sm|…|xl`, `--cc-focus-width|offset`, `--cc-control-height` (44px) and its `-sm`/`-lg` versions, `--cc-duration(-fast)`, `--cc-ease`, `--cc-z-float|sticky|overlay`. Breakpoints: 640, 768 and 1024px.
|
|
262
|
+
|
|
263
|
+
### Components
|
|
264
|
+
|
|
265
|
+
All text has Spanish defaults, and every label is an input.
|
|
266
|
+
|
|
267
|
+
| Component | Main inputs | Notes |
|
|
268
|
+
|---|---|---|
|
|
269
|
+
| `a[ccButton]`, `button[ccButton]` | `variant` (`primary`, `secondary`, `ghost`, `whatsapp`, `inverse`), `size` (`sm`, `md`, `lg`), `block` | The shared call-to-action style used by every component. |
|
|
270
|
+
| `<cc-plan-catalog>` | `plans`* (`null` = loading), `[(category)]`, `initialCategory`, `services`, `priceRanges`, `categories`, `categoriesLayout` (`auto`, `list`, `chips`), `showPrice`, `priceFormat`, `planMeta`, `cardAppearance`, `ctaLabel`, `ctaVariant`, `detailsLink`, `contactHref`, `emptyMessage`, `emptyActionLabel` | Full plan list page. It shows skeletons while loading, an empty state with actions, and a custom card through `<ng-template ccPlanCard let-plan let-link="link">`. |
|
|
271
|
+
| `<cc-plan-details>` | `plan`*, `bookingUrl`* (string or `(plan) => string`), `bookingLabel`, `barBookingLabel`, `bookingVariant`, `stickyBar`, `priceFormat`, `priceNote`, `perks`, `perksTitle`, `perksImageSrc`, icon inputs | It puts a booking button near the price and another at the end, and shows a fixed price and booking bar below 1024px. |
|
|
272
|
+
| `<cc-plan-card>` | `name`, `imageSrc`, `price`, `priceLabel`, `priceFormat`, `meta`, `link`, `queryParams`, `ctaLabel`, `ctaVariant`, `appearance` (`filled`, `outlined`, `plain`), `headingLevel`, `skeleton` | The whole card is clickable when it has a `link`. |
|
|
273
|
+
| `<cc-category-menu>` | `options`*, `[(selected)]`, `title`, `layout` | Toggle buttons with `aria-pressed`. |
|
|
274
|
+
| `<cc-search-box>` | `[(value)]`, `placeholder`, `label`, `iconSrc` | `search` output. |
|
|
275
|
+
| `<cc-plan-filter-form>` | `services`, `priceRanges`, `mode` (`instant`, `submit`), labels | `filterChange` output. |
|
|
276
|
+
| `<cc-page-banner>` | `title`*, `subtitle`, `variant` (`band`, `plain`), `size`, `italic`, `align`, `iconSrc`, `backLink` | Renders the page `<h1>`. |
|
|
277
|
+
| `<cc-section-heading>` | `title`*, `subtitle`, `eyebrow`, `iconSrc`, `level`, `size`, `italic`, `tone` (`default`, `inverse`, `accent`), `align`, `rule`, `headingId` | One heading pattern for every page section. |
|
|
278
|
+
| `<cc-gallery>` | `images`*, `columns`, `backgroundImage` | Opens `cc-lightbox`. `numberedImages(18, i => …)` builds the list. |
|
|
279
|
+
| `<cc-lightbox>` | `images`*, `[(index)]` | Arrows, swipe and Escape. Focus is trapped while open and restored on close. |
|
|
280
|
+
| `<cc-info-item>` | `title`*, `text`, `tone`, `size`, `headingLevel`, `headingId` | Projects extra content. |
|
|
281
|
+
| `<cc-notice>` | `tone` (`info`, `warning`, `success`), `title` | Highlighted note; content is projected. |
|
|
282
|
+
| `<cc-faq>` + `<cc-faq-item>` | `items` or projected `<cc-faq-item question="…">` | Native `<details>`, so answers are prerendered. Items can contain links. |
|
|
283
|
+
| `<cc-whatsapp-button>` | `href`*, `variant` (`icon`, `extended`), `label`, `size`, `position`, `iconSrc` | Floating button. |
|
|
284
|
+
| `<cc-promo-modal>` | `[(open)]`, `autoOpen`, `delayMs`, `rememberKey`, `rememberDays`, `imageSrc`, `imageAlt`, `link`, `ctaLabel`, `ctaHref` | It opens by itself in the browser and remembers the dismissal. |
|
|
285
|
+
| `<cc-social-links>` | `links`*, `size` (`sm`, `md`, `lg`), `tone` (`default`, `inverse`) | 44px tap area per link. |
|
|
286
|
+
|
|
287
|
+
`*` required. Each component also exposes its own `--cc-<component>-*` variables, which are listed in its JSDoc (`Tokens: …`).
|
|
288
|
+
|
|
289
|
+
### Services and utilities
|
|
290
|
+
|
|
291
|
+
- `PlanCatalogService`: `getPlans()` (with `additionalServices` joined), `getAdditionalServices()`, `getPriceRanges()`, `getPlanBySlug()`, `getPlansByCategory()`, `getPlansByFilter()`, `getPlansByName()`. Each JSON file is requested once and cached. Configure the paths with `providePlanCatalog({ plansUrl, additionalsUrl, priceRangesUrl })`.
|
|
292
|
+
- `SeoService`: `update({ title, description, path, image })`, `setJsonLd(id, data)`, `removeJsonLd(id)`, `absoluteUrl(path)`.
|
|
293
|
+
- Pure functions (no Angular): `formatPrice(value, { locale, currency, digits })` (default `es-CO`/`COP`: `$ 259.900`), `slugify`, `planSlug`, `findPlanBySlug`, `filterPlans`, `filterPlansByCategory`, `searchPlansByName`, `withCategoryCounts`, `joinAdditionalServices`, `defaultPlanMeta`, `whatsappUrl(phone, message)`, `titleCase`, `truncateText`.
|
|
294
|
+
|
|
295
|
+
### Migrating from 1.3
|
|
296
|
+
|
|
297
|
+
- The library no longer defines `--cc-primary`, `--cc-secondary`, `--cc-bg` or the other palette variables. Set the roles listed above from your own brand variables instead.
|
|
298
|
+
- Default colors are now neutral grays, and `--cc-on-accent` must be set when the accent is light.
|
|
299
|
+
- `cc-social-links`: `size` is now `sm`, `md` or `lg`, and `gap` became the `--cc-social-gap` token.
|
|
300
|
+
- `cc-plan-catalog`: `plans` accepts `null` (loading), and the category is the `[(category)]` model. The old `categoryChange` output still works, because it is the model's change event.
|
|
301
|
+
- `cc-promo-modal`: `open` now defaults to `false`; use `autoOpen` to open it by itself.
|
|
302
|
+
- `cc-plan-details`: prices use `formatPrice` (`priceFormat` input) instead of the currency pipe inputs.
|
|
303
|
+
|
|
304
|
+
### Development
|
|
305
|
+
|
|
306
|
+
- `npx ng serve showcase` runs a playground with every component. It loads the data and images from `../medellin-spa/src/assets`. Add `?theme=laurel` or `?theme=xora` to the URL to try a site theme; without it, the neutral defaults show.
|
|
307
|
+
- `npm run lint:ui` checks the architecture rules in `.claude/rules/ui-components.md`.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
193
311
|
## Contributing
|
|
194
312
|
|
|
195
313
|
Feel free to contribute to this library by submitting issues or pull requests.
|