srcdev-nuxt-components 9.1.17 → 9.1.19

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.
@@ -20,7 +20,13 @@
20
20
  "Bash(npx nuxi:*)",
21
21
  "Bash(node -e \"const t = require\\('/Users/simoncornforth/websites/nuxt-components/node_modules/pinia-plugin-persistedstate'\\); console.log\\(Object.keys\\(t\\)\\)\")",
22
22
  "Bash(npx vue-tsc:*)",
23
- "Bash(git -C /Users/simoncornforth/websites/nuxt-components log --oneline -5)"
23
+ "Bash(git -C /Users/simoncornforth/websites/nuxt-components log --oneline -5)",
24
+ "Bash(git -C /Users/simoncornforth/websites/nuxt-components show 16ac4ef --stat)",
25
+ "Bash(git -C /Users/simoncornforth/websites/nuxt-components log --oneline -8)",
26
+ "Bash(git -C /Users/simoncornforth/websites/nuxt-components show 5597a15 --stat)",
27
+ "Bash(git -C /Users/simoncornforth/websites/nuxt-components show 5597a15 -- \"*.vue\" \"*.css\")",
28
+ "Bash(npm install:*)",
29
+ "Bash(npm run:*)"
24
30
  ],
25
31
  "additionalDirectories": [
26
32
  "/Users/simoncornforth/websites/nuxt-components/app/components/01.atoms/content-wrappers/content-width",
@@ -48,10 +48,19 @@ import type { NavItem, NavItemData } from "~/types/components/navigation-horizon
48
48
 
49
49
  ## Consuming app usage
50
50
 
51
- Once published, consumers import from the package barrel:
51
+ The chain that makes this work:
52
+
53
+ ```text
54
+ app/types/components/<component>.d.ts
55
+ → app/types/components/index.ts (export * from "./<component>.d")
56
+ → types.d.ts (export * from "./app/types/components")
57
+ → consumer import
58
+ ```
59
+
60
+ `types.d.ts` is the `"types"` entry point in `package.json`, so once a type is added to the barrel it is importable directly from the package name:
52
61
 
53
62
  ```ts
54
- import type { NavItem, NavItemData } from "nuxt-components/app/types/components";
63
+ import type { NavItem, NavItemData } from "srcdev-nuxt-components";
55
64
  ```
56
65
 
57
66
  ## Notes
@@ -20,9 +20,19 @@ Both the horizontal list and the panel include animated active/hover indicator d
20
20
 
21
21
  ## NavItemData type
22
22
 
23
+ **Within the layer:**
24
+
23
25
  ```ts
24
26
  import type { NavItemData } from "~/types/components/navigation-horizontal.d";
27
+ ```
25
28
 
29
+ **In a consuming app:**
30
+
31
+ ```ts
32
+ import type { NavItemData } from "srcdev-nuxt-components";
33
+ ```
34
+
35
+ ```ts
26
36
  const navItemData: NavItemData = {
27
37
  main: [
28
38
  { text: "Home", href: "/" },
@@ -0,0 +1,120 @@
1
+ # SocialIconsList Component
2
+
3
+ ## Overview
4
+
5
+ `SocialIconsList` renders a horizontal list of social network icon links. Each item is data-driven via the `items` prop — the component composes the full href from `baseHref + profileId` at render time. Icons are sourced from the `logos:*` Iconify collection (`@iconify-json/logos`), which uses brand colours baked into the SVG.
6
+
7
+ ---
8
+
9
+ ## Props reference
10
+
11
+ | Prop | Type | Default | Notes |
12
+ |------|------|---------|-------|
13
+ | `items` | `ISocialIcon[]` | — | **Required.** Array of social network items. |
14
+ | `label` | `string` | `"Social media profiles"` | `aria-label` applied to the `<ul>` element. |
15
+ | `styleClassPassthrough` | `string \| string[]` | `[]` | Extra CSS classes applied to the root `<ul>`. |
16
+
17
+ ---
18
+
19
+ ## ISocialIcon type
20
+
21
+ ```ts
22
+ interface ISocialIcon {
23
+ networkName: string; // Used as aria-label: "{networkName} profile"
24
+ iconName: string; // Iconify icon name, e.g. "logos:instagram-icon"
25
+ baseHref: string; // Base URL including trailing slash, e.g. "https://www.instagram.com/"
26
+ profileId: string; // Profile identifier appended to baseHref
27
+ }
28
+ ```
29
+
30
+ The rendered `href` is `${baseHref}${profileId}`.
31
+
32
+ ### Importing the type
33
+
34
+ **Within the layer** (e.g. in another layer component or composable):
35
+
36
+ ```ts
37
+ import type { ISocialIcon } from "~/types/components/social-icons-list.d";
38
+ ```
39
+
40
+ **In a consuming app** — exported via the package barrel (`types.d.ts` → `app/types/components/index.ts`):
41
+
42
+ ```ts
43
+ import type { ISocialIcon } from "srcdev-nuxt-components";
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Standard social network values
49
+
50
+ | Network | `iconName` | `baseHref` |
51
+ |---------|-----------|-----------|
52
+ | Facebook | `logos:facebook` | `https://www.facebook.com/` |
53
+ | X (Twitter) | `logos:x` | `https://x.com/` |
54
+ | Instagram | `logos:instagram-icon` | `https://www.instagram.com/` |
55
+ | YouTube | `logos:youtube-icon` | `https://www.youtube.com/@` |
56
+ | TikTok | `logos:tiktok-icon` | `https://www.tiktok.com/@` |
57
+
58
+ ---
59
+
60
+ ## Usage example
61
+
62
+ ```vue
63
+ <SocialIconsList
64
+ :items="[
65
+ {
66
+ networkName: 'Instagram',
67
+ iconName: 'logos:instagram-icon',
68
+ baseHref: 'https://www.instagram.com/',
69
+ profileId: 'yourbrand',
70
+ },
71
+ {
72
+ networkName: 'TikTok',
73
+ iconName: 'logos:tiktok-icon',
74
+ baseHref: 'https://www.tiktok.com/@',
75
+ profileId: 'yourbrand',
76
+ },
77
+ ]"
78
+ />
79
+ ```
80
+
81
+ ---
82
+
83
+ ## CSS custom properties
84
+
85
+ | Property | Default | Notes |
86
+ |----------|---------|-------|
87
+ | `--theme-social-icon-size` | `2.4rem` | Width and height of each icon |
88
+ | `--theme-social-icon-gap` | `1.2rem` | Gap between icons in the flex row |
89
+
90
+ > **Note:** Iconify's `logos:*` styles are injected outside any CSS `@layer`, which means they override layered component styles. Icon sizing is applied via an inline `style` attribute on the `<Icon>` element so it takes precedence.
91
+
92
+ ---
93
+
94
+ ## Local style override scaffold
95
+
96
+ ```vue
97
+ <SocialIconsList :style-class-passthrough="['my-social-icons']" :items="items" />
98
+
99
+ <style>
100
+ /* ─── SocialIconsList local overrides ──────────────────────────────
101
+ Geometry and size only — brand colours are baked into logos: SVGs.
102
+ Delete this block if no overrides are needed.
103
+ ─────────────────────────────────────────────────────────────────── */
104
+ .social-icons-list {
105
+ &.my-social-icons {
106
+ /* --theme-social-icon-size: 3.2rem; */
107
+ /* --theme-social-icon-gap: 2rem; */
108
+ }
109
+ }
110
+ </style>
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Notes
116
+
117
+ - All links open in a new tab with `rel="noopener noreferrer"`.
118
+ - Each link carries `aria-label="{networkName} profile"` for screen reader accessibility.
119
+ - The `logos:*` Iconify collection requires `@iconify-json/logos` to be installed in the consumer app. Without it, icons will fall back to a CDN fetch (causing FOUC). See [icon-sets.md](../icon-sets.md).
120
+ - Auto-imported in Nuxt — no manual import needed.
@@ -36,6 +36,7 @@ Each skill is a single markdown file named `<area>-<task>.md`.
36
36
  ├── component-inline-action-button.md — InputButtonCore variant="inline" pattern for buttons embedded in custom input wrappers
37
37
  ├── icon-sets.md — icon set packages required by layer components, FOUC prevention, component→package map
38
38
  ├── robots-env-aware.md — @nuxtjs/robots: allow crawling on prod domain only, block on preview/staging via env var
39
+ ├── release-notes.md — produce release notes as a fenced markdown block from git log
39
40
  ├── composable-whatsapp.md — useWhatsApp: open pre-filled wa.me link from form payload; runtime config, security, usage
40
41
  ├── composable-zod-validation.md — useZodValidation: schema-driven form validation, error binding, submit flow, API error push
41
42
  ├── composable-colour-scheme.md — useColourScheme: reactive light/dark/auto switching, localStorage persistence, runtime config
@@ -58,7 +59,8 @@ Each skill is a single markdown file named `<area>-<task>.md`.
58
59
  ├── glass-panel.md — GlassPanel props, slots, CSS token API (--glass-panel-bg/border-color/shadow/highlight), theming override
59
60
  ├── navigation-horizontal.md — NavigationHorizontal props, NavItemData type, CSS token API, import path gotcha
60
61
  ├── input-copy-core.md — InputCopyCore: readonly copy-to-clipboard input; props, emits, slots, CSS classes, usage
61
- └── site-navigation.md — SiteNavigation: responsive nav with auto-collapse, burger menu, decorator indicators, CSS token API
62
+ ├── site-navigation.md — SiteNavigation: responsive nav with auto-collapse, burger menu, decorator indicators, CSS token API
63
+ └── social-icons-list.md — SocialIconsList: data-driven social icon links, ISocialIcon type, logos: icon names, CSS tokens
62
64
  ```
63
65
 
64
66
  ## Skill file template
@@ -0,0 +1,48 @@
1
+ # Release Notes
2
+
3
+ ## Overview
4
+
5
+ When asked to create release notes, always produce a fenced markdown code block (` ```markdown `) so the content can be copied and pasted directly into a git tag, GitHub release, or changelog.
6
+
7
+ ## Steps
8
+
9
+ ### 1. Determine the version
10
+
11
+ Run `git log --oneline -8` to find the most recent release commit and the commits since the previous release.
12
+
13
+ ### 2. Review the diff
14
+
15
+ Run `git show <commit> --stat` for each commit since the last release to understand what changed.
16
+
17
+ ### 3. Produce a fenced markdown block
18
+
19
+ Always wrap the output in a ` ```markdown ` code fence — never render it as plain markdown. This ensures the user can copy the raw text without formatting being stripped.
20
+
21
+ ## Format
22
+
23
+ ```markdown
24
+ ## vX.Y.Z
25
+
26
+ ### New
27
+
28
+ - **`ComponentOrComposableName`** — one-line description of what it does and why it exists
29
+
30
+ ### Fixed
31
+
32
+ - Short description of what was wrong and what was corrected
33
+
34
+ ### Changed
35
+
36
+ - Short description of intentional behaviour or API changes
37
+
38
+ ### Documentation
39
+
40
+ - **`skill-name` skill** — new/updated: what it covers
41
+ ```
42
+
43
+ ## Notes
44
+
45
+ - Only include sections that have content — omit empty headings
46
+ - Keep each bullet to one line where possible
47
+ - Lead with the most user-facing changes (New, Fixed) before internal ones (Documentation, Tests)
48
+ - Test additions warrant their own section only when substantial; otherwise fold into the relevant New/Fixed bullet
@@ -1,4 +1,6 @@
1
1
  :where(html) {
2
+ --field-margin-block: 0 1.6rem; /* space between field and other elements */
3
+
2
4
  /* Field spacing */
3
5
  --field-gap-block: 0.8rem; /* space between stacked fields */
4
6
  --field-gap-inline: 0;
@@ -0,0 +1,90 @@
1
+ <template>
2
+ <ul class="social-icons-list" :class="[elementClasses]" :aria-label="label">
3
+ <li v-for="item in items" :key="item.networkName" class="social-icon-item">
4
+ <a
5
+ :href="`${item.baseHref}${item.profileId}`"
6
+ class="social-icon-link"
7
+ :aria-label="`${item.networkName} profile`"
8
+ rel="noopener noreferrer"
9
+ target="_blank"
10
+ >
11
+ <Icon
12
+ :name="item.iconName"
13
+ class="social-icon"
14
+ :style="{ width: 'var(--_icon-size)', height: 'var(--_icon-size)' }"
15
+ />
16
+ </a>
17
+ </li>
18
+ </ul>
19
+ </template>
20
+
21
+ <script setup lang="ts">
22
+ import type { ISocialIcon } from "~/types/components/social-icons-list.d";
23
+
24
+ interface Props {
25
+ items: ISocialIcon[];
26
+ label?: string;
27
+ styleClassPassthrough?: string | string[];
28
+ }
29
+
30
+ const props = withDefaults(defineProps<Props>(), {
31
+ label: "Social media profiles",
32
+ styleClassPassthrough: () => [],
33
+ });
34
+
35
+ const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
36
+
37
+ watch(
38
+ () => props.styleClassPassthrough,
39
+ () => {
40
+ resetElementClasses(props.styleClassPassthrough);
41
+ }
42
+ );
43
+ </script>
44
+
45
+ <style lang="css">
46
+ @layer components {
47
+ .social-icons-list {
48
+ --_icon-size: var(--theme-social-icon-size, 2.4rem);
49
+ --_gap: var(--theme-social-icon-gap, 1.2rem);
50
+
51
+ display: flex;
52
+ flex-wrap: wrap;
53
+ gap: var(--_gap);
54
+ list-style: none;
55
+ padding: 0;
56
+ margin: 0;
57
+
58
+ .social-icon-item {
59
+ display: flex;
60
+
61
+ .social-icon-link {
62
+ display: flex;
63
+ align-items: center;
64
+ justify-content: center;
65
+ text-decoration: none;
66
+ transition:
67
+ transform 200ms ease,
68
+ opacity 200ms ease;
69
+
70
+ &:hover,
71
+ &:focus-visible {
72
+ transform: scale(1.15);
73
+ opacity: 0.85;
74
+ }
75
+
76
+ &:focus-visible {
77
+ outline: 2px solid currentColor;
78
+ outline-offset: 3px;
79
+ border-radius: 2px;
80
+ }
81
+
82
+ .social-icon {
83
+ /* width: var(--_icon-size); */
84
+ /* height: var(--_icon-size); */
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ </style>
@@ -0,0 +1,111 @@
1
+ import SocialIconsList from "../SocialIconsList.vue";
2
+ import type { Meta, StoryObj } from "@nuxtjs/storybook";
3
+ import type { ISocialIcon } from "~/types/components/social-icons-list.d";
4
+
5
+ const sampleItems: ISocialIcon[] = [
6
+ {
7
+ networkName: "Facebook",
8
+ iconName: "logos:facebook",
9
+ baseHref: "https://www.facebook.com/",
10
+ profileId: "yourprofile",
11
+ },
12
+ {
13
+ networkName: "X (Twitter)",
14
+ iconName: "logos:x",
15
+ baseHref: "https://x.com/",
16
+ profileId: "yourhandle",
17
+ },
18
+ {
19
+ networkName: "Instagram",
20
+ iconName: "logos:instagram-icon",
21
+ baseHref: "https://www.instagram.com/",
22
+ profileId: "yourprofile",
23
+ },
24
+ {
25
+ networkName: "YouTube",
26
+ iconName: "logos:youtube-icon",
27
+ baseHref: "https://www.youtube.com/@",
28
+ profileId: "yourchannel",
29
+ },
30
+ {
31
+ networkName: "TikTok",
32
+ iconName: "logos:tiktok-icon",
33
+ baseHref: "https://www.tiktok.com/@",
34
+ profileId: "yourprofile",
35
+ },
36
+ ];
37
+
38
+ const meta: Meta<typeof SocialIconsList> = {
39
+ title: "Molecules/SocialIconsList",
40
+ component: SocialIconsList,
41
+ argTypes: {
42
+ items: {
43
+ control: "object",
44
+ description:
45
+ "Array of social network items. Each item requires networkName, iconName (Iconify logos: collection), baseHref, and profileId.",
46
+ },
47
+ label: {
48
+ control: "text",
49
+ description: "aria-label for the list element",
50
+ },
51
+ styleClassPassthrough: {
52
+ control: "object",
53
+ description: "Additional CSS classes applied to the root element",
54
+ },
55
+ },
56
+ args: {
57
+ items: sampleItems,
58
+ label: "Social media profiles",
59
+ styleClassPassthrough: ["m-40"],
60
+ },
61
+ };
62
+
63
+ export default meta;
64
+ type Story = StoryObj<typeof SocialIconsList>;
65
+
66
+ // ─── Stories ─────────────────────────────────────────────────────────────────
67
+
68
+ /** Default — all five networks at the standard icon size. */
69
+ export const Default: Story = {
70
+ render: (args) => ({
71
+ components: { SocialIconsList },
72
+ setup() {
73
+ return { args };
74
+ },
75
+ template: `<SocialIconsList v-bind="args" />`,
76
+ }),
77
+ };
78
+
79
+ /** Large icons — override icon size via CSS token. */
80
+ export const LargeIcons: Story = {
81
+ name: "Large Icons",
82
+ render: (args) => ({
83
+ components: { SocialIconsList },
84
+ setup() {
85
+ return { args };
86
+ },
87
+ template: `<SocialIconsList v-bind="args" style="--theme-social-icon-size: 4rem;" />`,
88
+ }),
89
+ };
90
+
91
+ /** Single network — only one item in the list. */
92
+ export const SingleNetwork: Story = {
93
+ name: "Single Network",
94
+ args: {
95
+ items: [
96
+ {
97
+ networkName: "Instagram",
98
+ iconName: "logos:instagram-icon",
99
+ baseHref: "https://www.instagram.com/",
100
+ profileId: "luxurylocs",
101
+ },
102
+ ],
103
+ },
104
+ render: (args) => ({
105
+ components: { SocialIconsList },
106
+ setup() {
107
+ return { args };
108
+ },
109
+ template: `<SocialIconsList v-bind="args" />`,
110
+ }),
111
+ };
@@ -0,0 +1,124 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { mountSuspended } from "@nuxt/test-utils/runtime";
3
+ import SocialIconsList from "../SocialIconsList.vue";
4
+ import type { ISocialIcon } from "~/types/components/social-icons-list.d";
5
+
6
+ const defaultItems: ISocialIcon[] = [
7
+ {
8
+ networkName: "Facebook",
9
+ iconName: "logos:facebook",
10
+ baseHref: "https://www.facebook.com/",
11
+ profileId: "testprofile",
12
+ },
13
+ {
14
+ networkName: "Instagram",
15
+ iconName: "logos:instagram-icon",
16
+ baseHref: "https://www.instagram.com/",
17
+ profileId: "testhandle",
18
+ },
19
+ {
20
+ networkName: "YouTube",
21
+ iconName: "logos:youtube-icon",
22
+ baseHref: "https://www.youtube.com/@",
23
+ profileId: "testchannel",
24
+ },
25
+ ];
26
+
27
+ describe("SocialIconsList", () => {
28
+ it("mounts without error", async () => {
29
+ const wrapper = await mountSuspended(SocialIconsList, {
30
+ props: { items: defaultItems },
31
+ });
32
+ expect(wrapper.vm).toBeTruthy();
33
+ });
34
+
35
+ it("renders as a ul element", async () => {
36
+ const wrapper = await mountSuspended(SocialIconsList, {
37
+ props: { items: defaultItems },
38
+ });
39
+ expect(wrapper.element.tagName.toLowerCase()).toBe("ul");
40
+ });
41
+
42
+ it("renders the correct number of list items", async () => {
43
+ const wrapper = await mountSuspended(SocialIconsList, {
44
+ props: { items: defaultItems },
45
+ });
46
+ expect(wrapper.findAll(".social-icon-item").length).toBe(defaultItems.length);
47
+ });
48
+
49
+ it("renders the correct href for each item", async () => {
50
+ const wrapper = await mountSuspended(SocialIconsList, {
51
+ props: { items: defaultItems },
52
+ });
53
+ const links = wrapper.findAll(".social-icon-link");
54
+ defaultItems.forEach((item, i) => {
55
+ expect(links[i]!.attributes("href")).toBe(`${item.baseHref}${item.profileId}`);
56
+ });
57
+ });
58
+
59
+ it("renders aria-label on each link using networkName", async () => {
60
+ const wrapper = await mountSuspended(SocialIconsList, {
61
+ props: { items: defaultItems },
62
+ });
63
+ const links = wrapper.findAll(".social-icon-link");
64
+ defaultItems.forEach((item, i) => {
65
+ expect(links[i]!.attributes("aria-label")).toBe(`${item.networkName} profile`);
66
+ });
67
+ });
68
+
69
+ it("adds rel='noopener noreferrer' to each link", async () => {
70
+ const wrapper = await mountSuspended(SocialIconsList, {
71
+ props: { items: defaultItems },
72
+ });
73
+ const links = wrapper.findAll(".social-icon-link");
74
+ links.forEach((link) => {
75
+ expect(link.attributes("rel")).toBe("noopener noreferrer");
76
+ });
77
+ });
78
+
79
+ it("opens each link in a new tab", async () => {
80
+ const wrapper = await mountSuspended(SocialIconsList, {
81
+ props: { items: defaultItems },
82
+ });
83
+ const links = wrapper.findAll(".social-icon-link");
84
+ links.forEach((link) => {
85
+ expect(link.attributes("target")).toBe("_blank");
86
+ });
87
+ });
88
+
89
+ it("uses the default aria-label on the list", async () => {
90
+ const wrapper = await mountSuspended(SocialIconsList, {
91
+ props: { items: defaultItems },
92
+ });
93
+ expect(wrapper.attributes("aria-label")).toBe("Social media profiles");
94
+ });
95
+
96
+ it("uses a custom label prop as aria-label on the list", async () => {
97
+ const wrapper = await mountSuspended(SocialIconsList, {
98
+ props: { items: defaultItems, label: "Follow us" },
99
+ });
100
+ expect(wrapper.attributes("aria-label")).toBe("Follow us");
101
+ });
102
+
103
+ it("renders an empty list when items is empty", async () => {
104
+ const wrapper = await mountSuspended(SocialIconsList, {
105
+ props: { items: [] },
106
+ });
107
+ expect(wrapper.findAll(".social-icon-item").length).toBe(0);
108
+ });
109
+
110
+ it("applies styleClassPassthrough classes to the root element", async () => {
111
+ const wrapper = await mountSuspended(SocialIconsList, {
112
+ props: { items: defaultItems, styleClassPassthrough: ["custom-class", "another-class"] },
113
+ });
114
+ expect(wrapper.classes()).toContain("custom-class");
115
+ expect(wrapper.classes()).toContain("another-class");
116
+ });
117
+
118
+ it("renders the correct HTML structure", async () => {
119
+ const wrapper = await mountSuspended(SocialIconsList, {
120
+ props: { items: defaultItems },
121
+ });
122
+ expect(wrapper.html()).toMatchSnapshot();
123
+ });
124
+ });
@@ -0,0 +1,9 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`SocialIconsList > renders the correct HTML structure 1`] = `
4
+ "<ul class="social-icons-list" aria-label="Social media profiles">
5
+ <li class="social-icon-item"><a href="https://www.facebook.com/testprofile" class="social-icon-link" aria-label="Facebook profile" rel="noopener noreferrer" target="_blank"><span class="iconify i-logos:facebook social-icon" aria-hidden="true" style="width: var(--_icon-size); height: var(--_icon-size);"></span></a></li>
6
+ <li class="social-icon-item"><a href="https://www.instagram.com/testhandle" class="social-icon-link" aria-label="Instagram profile" rel="noopener noreferrer" target="_blank"><span class="iconify i-logos:instagram-icon social-icon" aria-hidden="true" style="width: var(--_icon-size); height: var(--_icon-size);"></span></a></li>
7
+ <li class="social-icon-item"><a href="https://www.youtube.com/@testchannel" class="social-icon-link" aria-label="YouTube profile" rel="noopener noreferrer" target="_blank"><span class="iconify i-logos:youtube-icon social-icon" aria-hidden="true" style="width: var(--_icon-size); height: var(--_icon-size);"></span></a></li>
8
+ </ul>"
9
+ `;
@@ -34,48 +34,48 @@ defineProps({
34
34
 
35
35
  <style lang="css">
36
36
  @layer components {
37
- .form-field {
38
- --_gutter-width: 0rem;
39
- --_max-width: 400px;
40
- --_background-color: transparent;
41
- --_border-radius: 0.4rem;
37
+ .form-field {
38
+ --_gutter-width: 0rem;
39
+ --_max-width: 400px;
40
+ --_background-color: transparent;
41
+ --_border-radius: 0.4rem;
42
42
 
43
- background-color: var(--_background-color);
44
- border-radius: var(--_border-radius);
45
- margin-inline: auto;
46
- margin-block: 0 1rem;
43
+ background-color: var(--_background-color);
44
+ border-radius: var(--_border-radius);
45
+ margin-inline: auto;
46
+ margin-block: var(--field-margin-block);
47
47
 
48
- width: min(100% - calc(2 * var(--_gutter-width)), var(--_max-width));
49
- outline: 0rem solid var(--slate-05);
50
- /* overflow-block: hidden; */
48
+ width: min(100% - calc(2 * var(--_gutter-width)), var(--_max-width));
49
+ outline: 0rem solid var(--slate-05);
50
+ /* overflow-block: hidden; */
51
51
 
52
- &:has(.underline) {
53
- --_background-color: var(--theme-form-input-bg-underlined);
54
- }
52
+ &:has(.underline) {
53
+ --_background-color: var(--theme-form-input-bg-underlined);
54
+ }
55
55
 
56
- .form-field-inner {
57
- background-color: var(--_background-color);
58
- border-radius: var(--_border-radius);
59
- margin-inline-start: 0rem;
60
- padding-inline-start: 0rem;
61
- outline: 0 solid var(--slate-05);
62
- }
56
+ .form-field-inner {
57
+ background-color: var(--_background-color);
58
+ border-radius: var(--_border-radius);
59
+ margin-inline-start: 0rem;
60
+ padding-inline-start: 0rem;
61
+ outline: 0 solid var(--slate-05);
62
+ }
63
63
 
64
- &.has-gutter {
65
- --_gutter-width: 1.6rem;
66
- }
64
+ &.has-gutter {
65
+ --_gutter-width: 1.6rem;
66
+ }
67
67
 
68
- &.narrow {
69
- max-width: 400px;
70
- }
68
+ &.narrow {
69
+ max-width: 400px;
70
+ }
71
71
 
72
- &.medium {
73
- --_max-width: 800px;
74
- }
72
+ &.medium {
73
+ --_max-width: 800px;
74
+ }
75
75
 
76
- &.wide {
77
- --_max-width: 1200px;
76
+ &.wide {
77
+ --_max-width: 1200px;
78
+ }
78
79
  }
79
80
  }
80
- }
81
81
  </style>
@@ -1,5 +1,3 @@
1
- // composables/useWhatsApp.ts
2
-
3
1
  export const useWhatsApp = () => {
4
2
  const config = useRuntimeConfig();
5
3
 
@@ -10,3 +10,4 @@ export * from "./qr-code.d"
10
10
  export * from "./alert-mask-core.d"
11
11
  export * from "./hero-text"
12
12
  export * from "./navigation-horizontal.d"
13
+ export * from "./social-icons-list.d"
@@ -0,0 +1,6 @@
1
+ export interface ISocialIcon {
2
+ networkName: string;
3
+ iconName: string;
4
+ baseHref: string;
5
+ profileId: string;
6
+ }
@@ -12,6 +12,7 @@ const ICON_SETS = [
12
12
  "@iconify-json/bitcoin-icons",
13
13
  "@iconify-json/gravity-ui",
14
14
  "@iconify-json/ic",
15
+ "@iconify-json/logos",
15
16
  "@iconify-json/lucide",
16
17
  "@iconify-json/material-symbols",
17
18
  "@iconify-json/mdi",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "9.1.17",
4
+ "version": "9.1.19",
5
5
  "main": "nuxt.config.ts",
6
6
  "types": "types.d.ts",
7
7
  "license": "MIT",
@@ -45,6 +45,7 @@
45
45
  "@iconify-json/bitcoin-icons": "*",
46
46
  "@iconify-json/gravity-ui": "*",
47
47
  "@iconify-json/ic": "*",
48
+ "@iconify-json/logos": "*",
48
49
  "@iconify-json/lucide": "*",
49
50
  "@iconify-json/material-symbols": "*",
50
51
  "@iconify-json/mdi": "*",
@@ -66,6 +67,9 @@
66
67
  "@iconify-json/ic": {
67
68
  "optional": true
68
69
  },
70
+ "@iconify-json/logos": {
71
+ "optional": true
72
+ },
69
73
  "@iconify-json/lucide": {
70
74
  "optional": true
71
75
  },
@@ -86,6 +90,7 @@
86
90
  "@iconify-json/bitcoin-icons": "1.2.4",
87
91
  "@iconify-json/gravity-ui": "1.2.12",
88
92
  "@iconify-json/ic": "*",
93
+ "@iconify-json/logos": "1.2.11",
89
94
  "@iconify-json/lucide": "*",
90
95
  "@iconify-json/material-symbols": "1.2.64",
91
96
  "@iconify-json/mdi": "1.2.3",