@xscriptor/xcomponents 0.1.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/CODE_OF_CONDUCT.md +35 -0
- package/CONTRIBUTING.md +64 -0
- package/LICENSE +21 -0
- package/README.md +127 -0
- package/SECURITY.md +25 -0
- package/dist/chunk-2OAXRRVQ.mjs +150 -0
- package/dist/chunk-2OAXRRVQ.mjs.map +1 -0
- package/dist/chunk-42XPBYTL.mjs +186 -0
- package/dist/chunk-42XPBYTL.mjs.map +1 -0
- package/dist/chunk-5G4P2E76.mjs +66 -0
- package/dist/chunk-5G4P2E76.mjs.map +1 -0
- package/dist/chunk-FZRTAML3.mjs +1 -0
- package/dist/chunk-FZRTAML3.mjs.map +1 -0
- package/dist/chunk-NY22GB3E.mjs +311 -0
- package/dist/chunk-NY22GB3E.mjs.map +1 -0
- package/dist/chunk-QCMWPIG7.mjs +320 -0
- package/dist/chunk-QCMWPIG7.mjs.map +1 -0
- package/dist/chunk-U27ZVCP7.mjs +247 -0
- package/dist/chunk-U27ZVCP7.mjs.map +1 -0
- package/dist/components/content/index.css +132 -0
- package/dist/components/content/index.css.map +1 -0
- package/dist/components/content/index.d.mts +17 -0
- package/dist/components/content/index.d.ts +17 -0
- package/dist/components/content/index.js +102 -0
- package/dist/components/content/index.js.map +1 -0
- package/dist/components/content/index.mjs +7 -0
- package/dist/components/content/index.mjs.map +1 -0
- package/dist/components/forms/index.css +307 -0
- package/dist/components/forms/index.css.map +1 -0
- package/dist/components/forms/index.d.mts +68 -0
- package/dist/components/forms/index.d.ts +68 -0
- package/dist/components/forms/index.js +357 -0
- package/dist/components/forms/index.js.map +1 -0
- package/dist/components/forms/index.mjs +9 -0
- package/dist/components/forms/index.mjs.map +1 -0
- package/dist/components/gallery/index.css +229 -0
- package/dist/components/gallery/index.css.map +1 -0
- package/dist/components/gallery/index.d.mts +29 -0
- package/dist/components/gallery/index.d.ts +29 -0
- package/dist/components/gallery/index.js +187 -0
- package/dist/components/gallery/index.js.map +1 -0
- package/dist/components/gallery/index.mjs +9 -0
- package/dist/components/gallery/index.mjs.map +1 -0
- package/dist/components/index.css +1181 -0
- package/dist/components/index.css.map +1 -0
- package/dist/components/index.d.mts +8 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.js +1317 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +50 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/components/layout/index.css +168 -0
- package/dist/components/layout/index.css.map +1 -0
- package/dist/components/layout/index.d.mts +55 -0
- package/dist/components/layout/index.d.ts +55 -0
- package/dist/components/layout/index.js +224 -0
- package/dist/components/layout/index.js.map +1 -0
- package/dist/components/layout/index.mjs +11 -0
- package/dist/components/layout/index.mjs.map +1 -0
- package/dist/components/navigation/index.css +229 -0
- package/dist/components/navigation/index.css.map +1 -0
- package/dist/components/navigation/index.d.mts +76 -0
- package/dist/components/navigation/index.d.ts +76 -0
- package/dist/components/navigation/index.js +347 -0
- package/dist/components/navigation/index.js.map +1 -0
- package/dist/components/navigation/index.mjs +7 -0
- package/dist/components/navigation/index.mjs.map +1 -0
- package/dist/components/social/index.css +116 -0
- package/dist/components/social/index.css.map +1 -0
- package/dist/components/social/index.d.mts +55 -0
- package/dist/components/social/index.d.ts +55 -0
- package/dist/components/social/index.js +280 -0
- package/dist/components/social/index.js.map +1 -0
- package/dist/components/social/index.mjs +21 -0
- package/dist/components/social/index.mjs.map +1 -0
- package/dist/index.css +1181 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1317 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +50 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our commitment
|
|
4
|
+
|
|
5
|
+
We are committed to making participation in this project a respectful,
|
|
6
|
+
harassment-free experience for everyone.
|
|
7
|
+
|
|
8
|
+
## Expected behavior
|
|
9
|
+
|
|
10
|
+
- Be respectful and constructive.
|
|
11
|
+
- Accept feedback with professionalism.
|
|
12
|
+
- Focus on what is best for the project and community.
|
|
13
|
+
- Show empathy toward other contributors.
|
|
14
|
+
|
|
15
|
+
## Unacceptable behavior
|
|
16
|
+
|
|
17
|
+
- Harassment, intimidation, or discrimination.
|
|
18
|
+
- Trolling, insulting, or derogatory comments.
|
|
19
|
+
- Publishing private information without permission.
|
|
20
|
+
- Any other conduct that is inappropriate in a professional setting.
|
|
21
|
+
|
|
22
|
+
## Enforcement
|
|
23
|
+
|
|
24
|
+
Project maintainers are responsible for clarifying standards and may take
|
|
25
|
+
appropriate action in response to unacceptable behavior.
|
|
26
|
+
|
|
27
|
+
## Reporting
|
|
28
|
+
|
|
29
|
+
To report behavior that violates this Code of Conduct, open a private security
|
|
30
|
+
report as described in SECURITY.md.
|
|
31
|
+
|
|
32
|
+
## Attribution
|
|
33
|
+
|
|
34
|
+
This document is adapted from common open-source community standards,
|
|
35
|
+
including the Contributor Covenant principles.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in improving @xscriptor/xcomponents.
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
|
|
7
|
+
This package contains reusable React/Next.js UI components.
|
|
8
|
+
Contributions should keep public APIs stable and types well documented.
|
|
9
|
+
|
|
10
|
+
## Development setup
|
|
11
|
+
|
|
12
|
+
1. Install dependencies:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
2. Build the package:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm run prepare:build
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
3. Validate the package content:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm pack --dry-run
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Contribution workflow
|
|
31
|
+
|
|
32
|
+
1. Create a feature branch from `dev`.
|
|
33
|
+
2. Keep changes focused and small.
|
|
34
|
+
3. Add or update examples when behavior changes.
|
|
35
|
+
4. Ensure build passes before opening a PR.
|
|
36
|
+
5. Open a pull request with:
|
|
37
|
+
- clear summary
|
|
38
|
+
- screenshots or usage snippet for UI changes
|
|
39
|
+
- migration note if API changed
|
|
40
|
+
|
|
41
|
+
## Coding guidelines
|
|
42
|
+
|
|
43
|
+
- Use TypeScript and exported prop types.
|
|
44
|
+
- Keep component names with `X` prefix.
|
|
45
|
+
- Prefer category barrels for exports.
|
|
46
|
+
- Avoid breaking changes unless explicitly discussed.
|
|
47
|
+
|
|
48
|
+
## Commit style
|
|
49
|
+
|
|
50
|
+
Use concise, imperative commit messages, for example:
|
|
51
|
+
|
|
52
|
+
- `feat(social): add XLinkedInIcon hover fill support`
|
|
53
|
+
- `fix(layout): correct zigzag spacing on mobile`
|
|
54
|
+
- `docs(readme): update publish steps`
|
|
55
|
+
|
|
56
|
+
## Reporting issues
|
|
57
|
+
|
|
58
|
+
Please include:
|
|
59
|
+
|
|
60
|
+
- expected behavior
|
|
61
|
+
- current behavior
|
|
62
|
+
- reproduction steps
|
|
63
|
+
- package version
|
|
64
|
+
- React/Next.js versions
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Xscriptor
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<h1 align="center">@xscriptor/xcomponents</h1>
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
Reusable React/Next.js component package by Xscriptor.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<br>
|
|
16
|
+
<hr>
|
|
17
|
+
|
|
18
|
+
<details open>
|
|
19
|
+
<summary><h2>Table of Contents</h2></summary>
|
|
20
|
+
<ul>
|
|
21
|
+
<li><a href="#overview">Overview</a></li>
|
|
22
|
+
<li><a href="#installation">Installation</a></li>
|
|
23
|
+
<li><a href="#usage">Usage</a></li>
|
|
24
|
+
<li><a href="#exports">Exports</a></li>
|
|
25
|
+
<li><a href="#project-structure">Project Structure</a></li>
|
|
26
|
+
<li><a href="#scripts">Scripts</a></li>
|
|
27
|
+
<li><a href="#packaging-and-publish">Packaging and Publish</a></li>
|
|
28
|
+
<li><a href="#related-documents">Related Documents</a></li>
|
|
29
|
+
</ul>
|
|
30
|
+
</details>
|
|
31
|
+
|
|
32
|
+
<hr>
|
|
33
|
+
|
|
34
|
+
<h2 id="overview">Overview</h2>
|
|
35
|
+
|
|
36
|
+
<p>
|
|
37
|
+
@xscriptor/xcomponents provides reusable UI building blocks for React and Next.js projects,
|
|
38
|
+
organized by category and exported with TypeScript declarations.
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
<h2 id="installation">Installation</h2>
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install @xscriptor/xcomponents
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
<h2 id="usage">Usage</h2>
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
import { XNavbar, XSeparator } from "@xscriptor/xcomponents";
|
|
51
|
+
import { XContactForm } from "@xscriptor/xcomponents/forms";
|
|
52
|
+
import { XSocialContact, XInstagramIcon } from "@xscriptor/xcomponents/social";
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
<h2 id="exports">Exports</h2>
|
|
56
|
+
|
|
57
|
+
<ul>
|
|
58
|
+
<li><code>@xscriptor/xcomponents</code> (root exports)</li>
|
|
59
|
+
<li><code>@xscriptor/xcomponents/forms</code></li>
|
|
60
|
+
<li><code>@xscriptor/xcomponents/navigation</code></li>
|
|
61
|
+
<li><code>@xscriptor/xcomponents/layout</code></li>
|
|
62
|
+
<li><code>@xscriptor/xcomponents/content</code></li>
|
|
63
|
+
<li><code>@xscriptor/xcomponents/gallery</code></li>
|
|
64
|
+
<li><code>@xscriptor/xcomponents/social</code></li>
|
|
65
|
+
</ul>
|
|
66
|
+
|
|
67
|
+
<h2 id="project-structure">Project Structure</h2>
|
|
68
|
+
|
|
69
|
+
<ul>
|
|
70
|
+
<li><code>src/components/forms</code></li>
|
|
71
|
+
<li><code>src/components/navigation</code></li>
|
|
72
|
+
<li><code>src/components/layout</code></li>
|
|
73
|
+
<li><code>src/components/content</code></li>
|
|
74
|
+
<li><code>src/components/gallery</code></li>
|
|
75
|
+
<li><code>src/components/social</code></li>
|
|
76
|
+
</ul>
|
|
77
|
+
|
|
78
|
+
<h2 id="scripts">Scripts</h2>
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm run build
|
|
82
|
+
npm run clean
|
|
83
|
+
npm run prepare:build
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
<h2 id="packaging-and-publish">Packaging and Publish</h2>
|
|
87
|
+
|
|
88
|
+
1. Authenticate with npm:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm login
|
|
92
|
+
npm whoami
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
2. Build and validate package content:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm run prepare:build
|
|
99
|
+
npm pack --dry-run
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
3. Bump version:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npm version patch
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
4. Publish package:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npm publish
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
<h2 id="related-documents">Related Documents</h2>
|
|
115
|
+
|
|
116
|
+
<ul>
|
|
117
|
+
<li><a href="./CONTRIBUTING.md">Contributing Guide</a></li>
|
|
118
|
+
<li><a href="./CODE_OF_CONDUCT.md">Code of Conduct</a></li>
|
|
119
|
+
<li><a href="./SECURITY.md">Security Policy</a></li>
|
|
120
|
+
<li><a href="./LICENSE">License (MIT)</a></li>
|
|
121
|
+
</ul>
|
|
122
|
+
|
|
123
|
+
<div align="center">
|
|
124
|
+
<h2>X</h2>
|
|
125
|
+
|
|
126
|
+
<a href="https://dev.xscriptor.com">XWeb</a> | <a href="https://dev.xscriptor.com">Profile</a>
|
|
127
|
+
</div>
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Security updates are applied to the latest published version of
|
|
6
|
+
`@xscriptor/xcomponents`.
|
|
7
|
+
|
|
8
|
+
| Version | Supported |
|
|
9
|
+
| --- | --- |
|
|
10
|
+
| latest | yes |
|
|
11
|
+
| older versions | no |
|
|
12
|
+
|
|
13
|
+
## Reporting a vulnerability
|
|
14
|
+
|
|
15
|
+
If you find a security vulnerability, please do not open a public issue first.
|
|
16
|
+
|
|
17
|
+
Send a private report including:
|
|
18
|
+
|
|
19
|
+
- a short description of the issue
|
|
20
|
+
- reproduction steps or proof of concept
|
|
21
|
+
- potential impact
|
|
22
|
+
- suggested mitigation (if available)
|
|
23
|
+
|
|
24
|
+
Maintainers will acknowledge receipt as soon as possible and coordinate a fix
|
|
25
|
+
before public disclosure.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// src/components/gallery/xmicrogallerytext/XMicroGalleryText.tsx
|
|
2
|
+
import React, { useEffect, useRef } from "react";
|
|
3
|
+
import Image from "next/image";
|
|
4
|
+
import { motion } from "framer-motion";
|
|
5
|
+
|
|
6
|
+
// src/components/gallery/xmicrogallerytext/XMicroGalleryText.module.css
|
|
7
|
+
var XMicroGalleryText_default = {};
|
|
8
|
+
|
|
9
|
+
// src/components/gallery/xmicrogallerytext/XMicroGalleryText.tsx
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
var DISPLAY_COUNT = 3;
|
|
12
|
+
var XMicroGalleryText = ({
|
|
13
|
+
images,
|
|
14
|
+
text,
|
|
15
|
+
textPosition = "left",
|
|
16
|
+
textAlign = "left",
|
|
17
|
+
autoShuffle = false,
|
|
18
|
+
shuffleInterval = 5e3
|
|
19
|
+
}) => {
|
|
20
|
+
const containerRef = useRef(null);
|
|
21
|
+
const [startIndex, setStartIndex] = React.useState(0);
|
|
22
|
+
const visibleImages = React.useMemo(() => {
|
|
23
|
+
const result = [];
|
|
24
|
+
for (let i = 0; i < DISPLAY_COUNT; i++) {
|
|
25
|
+
result.push(images[(startIndex + i) % images.length]);
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}, [images, startIndex]);
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
if (!autoShuffle || images.length <= DISPLAY_COUNT) return;
|
|
31
|
+
const intervalId = setInterval(() => {
|
|
32
|
+
setStartIndex((prev) => (prev + 1) % images.length);
|
|
33
|
+
}, shuffleInterval);
|
|
34
|
+
return () => clearInterval(intervalId);
|
|
35
|
+
}, [autoShuffle, shuffleInterval, images.length]);
|
|
36
|
+
const [isVisible, setIsVisible] = React.useState(false);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
const observer = new IntersectionObserver(
|
|
39
|
+
([entry]) => {
|
|
40
|
+
if (entry.isIntersecting) {
|
|
41
|
+
setIsVisible(true);
|
|
42
|
+
observer.disconnect();
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
threshold: 0.1,
|
|
47
|
+
rootMargin: "0px 0px -50px 0px"
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
if (containerRef.current) {
|
|
51
|
+
observer.observe(containerRef.current);
|
|
52
|
+
}
|
|
53
|
+
return () => observer.disconnect();
|
|
54
|
+
}, []);
|
|
55
|
+
const isTextRight = textPosition === "right";
|
|
56
|
+
const alignClass = {
|
|
57
|
+
left: XMicroGalleryText_default.textLeft,
|
|
58
|
+
right: XMicroGalleryText_default.textRight,
|
|
59
|
+
center: XMicroGalleryText_default.textCenter
|
|
60
|
+
}[textAlign];
|
|
61
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: `${XMicroGalleryText_default.container} ${isTextRight ? XMicroGalleryText_default.reverse : ""}`, children: [
|
|
62
|
+
/* @__PURE__ */ jsx("div", { className: `${XMicroGalleryText_default.textContent} ${alignClass} ${isVisible ? XMicroGalleryText_default.visible : ""}`, children: typeof text === "string" ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: text } }) : text }),
|
|
63
|
+
/* @__PURE__ */ jsx("div", { className: XMicroGalleryText_default.gallery, children: /* @__PURE__ */ jsx("div", { className: XMicroGalleryText_default.artisticGrid, children: visibleImages.map((image, index) => /* @__PURE__ */ jsx(
|
|
64
|
+
motion.div,
|
|
65
|
+
{
|
|
66
|
+
layout: true,
|
|
67
|
+
className: `${XMicroGalleryText_default.imageWrapper} ${XMicroGalleryText_default[`artistic${index + 1}`]} ${isVisible ? XMicroGalleryText_default.visible : ""}`,
|
|
68
|
+
style: { transitionProperty: "opacity, box-shadow" },
|
|
69
|
+
transition: {
|
|
70
|
+
layout: { type: "spring", stiffness: 80, damping: 20 }
|
|
71
|
+
},
|
|
72
|
+
children: /* @__PURE__ */ jsx(
|
|
73
|
+
Image,
|
|
74
|
+
{
|
|
75
|
+
src: image.src,
|
|
76
|
+
alt: image.alt,
|
|
77
|
+
fill: true,
|
|
78
|
+
className: XMicroGalleryText_default.previewImage,
|
|
79
|
+
sizes: "(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
},
|
|
83
|
+
image.src
|
|
84
|
+
)) }) })
|
|
85
|
+
] });
|
|
86
|
+
};
|
|
87
|
+
var XMicroGalleryText_default2 = XMicroGalleryText;
|
|
88
|
+
|
|
89
|
+
// src/components/gallery/xstaticgallery/XStaticGallery.tsx
|
|
90
|
+
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
91
|
+
import Image2 from "next/image";
|
|
92
|
+
|
|
93
|
+
// src/components/gallery/xstaticgallery/XStaticGallery.module.css
|
|
94
|
+
var XStaticGallery_default = {};
|
|
95
|
+
|
|
96
|
+
// src/components/gallery/xstaticgallery/XStaticGallery.tsx
|
|
97
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
98
|
+
var COLUMN_CLASSES = {
|
|
99
|
+
1: XStaticGallery_default.cols1,
|
|
100
|
+
2: XStaticGallery_default.cols2,
|
|
101
|
+
3: XStaticGallery_default.cols3,
|
|
102
|
+
4: XStaticGallery_default.cols4,
|
|
103
|
+
5: XStaticGallery_default.cols5
|
|
104
|
+
};
|
|
105
|
+
function XStaticGallery({ images, columns = 4, title }) {
|
|
106
|
+
const containerRef = useRef2(null);
|
|
107
|
+
useEffect2(() => {
|
|
108
|
+
const observer = new IntersectionObserver(
|
|
109
|
+
(entries) => {
|
|
110
|
+
entries.forEach((entry) => {
|
|
111
|
+
if (entry.isIntersecting) {
|
|
112
|
+
entry.target.classList.add(XStaticGallery_default.visible);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
threshold: 0.1,
|
|
118
|
+
rootMargin: "0px 0px -50px 0px"
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
const items = containerRef.current?.querySelectorAll(`.${XStaticGallery_default.masonryItem}`);
|
|
122
|
+
items?.forEach((el) => observer.observe(el));
|
|
123
|
+
return () => observer.disconnect();
|
|
124
|
+
}, []);
|
|
125
|
+
const colClass = COLUMN_CLASSES[columns] || COLUMN_CLASSES[4];
|
|
126
|
+
return /* @__PURE__ */ jsxs2("div", { ref: containerRef, className: XStaticGallery_default.galleryContainer, children: [
|
|
127
|
+
title && /* @__PURE__ */ jsx2("h2", { className: XStaticGallery_default.galleryTitle, children: title }),
|
|
128
|
+
/* @__PURE__ */ jsx2("div", { className: `${XStaticGallery_default.masonryGrid} ${colClass}`, children: images.map((image, index) => /* @__PURE__ */ jsx2("div", { className: XStaticGallery_default.masonryItem, children: /* @__PURE__ */ jsxs2("div", { className: XStaticGallery_default.imageContainer, children: [
|
|
129
|
+
/* @__PURE__ */ jsx2(
|
|
130
|
+
Image2,
|
|
131
|
+
{
|
|
132
|
+
src: image.src,
|
|
133
|
+
alt: image.alt,
|
|
134
|
+
width: 600,
|
|
135
|
+
height: 600,
|
|
136
|
+
className: XStaticGallery_default.galleryImage,
|
|
137
|
+
loading: "lazy",
|
|
138
|
+
sizes: "(max-width: 640px) 100vw, (max-width: 768px) 50vw, (max-width: 1280px) 33vw, 25vw"
|
|
139
|
+
}
|
|
140
|
+
),
|
|
141
|
+
/* @__PURE__ */ jsx2("div", { className: XStaticGallery_default.imageOverlay })
|
|
142
|
+
] }) }, index)) })
|
|
143
|
+
] });
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export {
|
|
147
|
+
XMicroGalleryText_default2 as XMicroGalleryText_default,
|
|
148
|
+
XStaticGallery
|
|
149
|
+
};
|
|
150
|
+
//# sourceMappingURL=chunk-2OAXRRVQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/gallery/xmicrogallerytext/XMicroGalleryText.tsx","../src/components/gallery/xmicrogallerytext/XMicroGalleryText.module.css","../src/components/gallery/xstaticgallery/XStaticGallery.tsx","../src/components/gallery/xstaticgallery/XStaticGallery.module.css"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\nimport Image from 'next/image';\nimport { motion } from 'framer-motion';\nimport styles from './XMicroGalleryText.module.css';\n\nexport interface XMicroGalleryImage {\n src: string;\n alt: string;\n}\n\nexport interface XMicroGalleryTextProps {\n images: XMicroGalleryImage[];\n text: React.ReactNode;\n textPosition?: 'left' | 'right';\n textAlign?: 'left' | 'right' | 'center';\n autoShuffle?: boolean;\n shuffleInterval?: number;\n}\n\nconst DISPLAY_COUNT = 3;\n\nconst XMicroGalleryText: React.FC<XMicroGalleryTextProps> = ({ \n images, \n text, \n textPosition = 'left',\n textAlign = 'left',\n autoShuffle = false,\n shuffleInterval = 5000\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const [startIndex, setStartIndex] = React.useState(0);\n\n const visibleImages = React.useMemo(() => {\n const result: XMicroGalleryImage[] = [];\n for (let i = 0; i < DISPLAY_COUNT; i++) {\n result.push(images[(startIndex + i) % images.length]);\n }\n return result;\n }, [images, startIndex]);\n\n React.useEffect(() => {\n if (!autoShuffle || images.length <= DISPLAY_COUNT) return;\n\n const intervalId = setInterval(() => {\n setStartIndex((prev) => (prev + 1) % images.length);\n }, shuffleInterval);\n\n return () => clearInterval(intervalId);\n }, [autoShuffle, shuffleInterval, images.length]);\n\n const [isVisible, setIsVisible] = React.useState(false);\n\n useEffect(() => {\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setIsVisible(true);\n observer.disconnect();\n }\n },\n {\n threshold: 0.1,\n rootMargin: '0px 0px -50px 0px'\n }\n );\n\n if (containerRef.current) {\n observer.observe(containerRef.current);\n }\n\n return () => observer.disconnect();\n }, []);\n\n const isTextRight = textPosition === 'right';\n\n const alignClass = {\n left: styles.textLeft,\n right: styles.textRight,\n center: styles.textCenter,\n }[textAlign];\n\n return (\n <div ref={containerRef} className={`${styles.container} ${isTextRight ? styles.reverse : ''}`}>\n <div className={`${styles.textContent} ${alignClass} ${isVisible ? styles.visible : ''}`}>\n {typeof text === 'string' ? (\n <div dangerouslySetInnerHTML={{ __html: text }} />\n ) : (\n text\n )}\n </div>\n \n <div className={styles.gallery}>\n <div className={styles.artisticGrid}>\n {visibleImages.map((image, index) => (\n <motion.div \n layout\n key={image.src} \n className={`${styles.imageWrapper} ${styles[`artistic${index + 1}`]} ${isVisible ? styles.visible : ''}`}\n style={{ transitionProperty: 'opacity, box-shadow' }}\n transition={{\n layout: { type: \"spring\", stiffness: 80, damping: 20 }\n }}\n >\n <Image\n src={image.src}\n alt={image.alt}\n fill\n className={styles.previewImage}\n sizes=\"(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw\"\n />\n </motion.div>\n ))}\n </div>\n </div>\n </div>\n );\n};\n\nexport default XMicroGalleryText;\n",".container {\n display: flex;\n flex-direction: column;\n gap: 2rem;\n width: 100%;\n align-items: center;\n margin: 2rem 0;\n}\n\n@media (min-width: 1024px) {\n .container {\n flex-direction: row;\n align-items: center;\n gap: 4rem;\n }\n \n .reverse {\n flex-direction: row-reverse;\n }\n}\n\n.textContent {\n flex: 1;\n opacity: 0;\n transform: translateY(30px);\n transition: opacity 0.8s ease-out, transform 0.8s ease-out;\n color: var(--foreground);\n}\n\n.textContent.visible {\n opacity: 1;\n transform: translateY(0);\n}\n\n.textLeft {\n text-align: left;\n}\n\n.textRight {\n text-align: right;\n}\n\n.textCenter {\n text-align: center;\n}\n\n.textContent p,\n.textContent div,\n.textContent span,\n.textContent em,\n.textContent strong,\n.textContent a {\n text-align: inherit;\n max-width: none;\n margin-left: unset;\n margin-right: unset;\n}\n\n.gallery {\n flex: 1.5;\n width: 100%;\n}\n\n.artisticGrid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n grid-template-rows: 380px 220px;\n gap: 1rem;\n}\n\n.imageWrapper {\n position: relative;\n overflow: hidden;\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);\n border-radius: 20px;\n opacity: 0;\n transform: translateY(50px) scale(0.95);\n transition: opacity 0.6s ease-out, transform 0.6s ease-out, box-shadow 0.3s ease;\n}\n\n.imageWrapper.visible {\n opacity: 1;\n transform: translateY(0) scale(1);\n}\n\n.imageWrapper:hover {\n transform: translateY(-5px);\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);\n}\n\n.previewImage {\n object-fit: cover;\n}\n\n.artisticGrid .artistic1 .previewImage {\n object-position: center top;\n transform: translateY(0);\n}\n\n.artistic1 {\n grid-column: 1 / 4;\n grid-row: 1 / 2;\n transition-delay: 0.2s;\n}\n\n.artistic2 {\n grid-column: 1 / 2;\n grid-row: 2 / 3;\n transition-delay: 0.3s;\n}\n\n.artistic3 {\n grid-column: 2 / 4;\n grid-row: 2 / 3;\n transition-delay: 0.4s;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .artisticGrid {\n grid-template-columns: 1fr;\n grid-template-rows: 240px 180px 180px;\n }\n \n .artistic1,\n .artistic2,\n .artistic3 {\n grid-column: 1 / 2;\n }\n \n .artistic1 {\n grid-row: 1 / 2;\n }\n \n .artistic2 {\n grid-row: 2 / 3;\n }\n \n .artistic3 {\n grid-row: 3 / 4;\n }\n}\n\n@media (max-width: 480px) {\n .artisticGrid {\n grid-template-rows: 200px 140px 140px;\n }\n}\n","\"use client\";\nimport React, { useEffect, useRef } from 'react';\nimport Image from 'next/image';\nimport styles from './XStaticGallery.module.css';\n\nexport interface XStaticGalleryImage {\n src: string;\n alt: string;\n}\n\nexport interface XStaticGalleryProps {\n images: XStaticGalleryImage[];\n columns?: 1 | 2 | 3 | 4 | 5;\n title?: string;\n}\n\nconst COLUMN_CLASSES: Record<number, string> = {\n 1: styles.cols1,\n 2: styles.cols2,\n 3: styles.cols3,\n 4: styles.cols4,\n 5: styles.cols5,\n};\n\nexport default function XStaticGallery({ images, columns = 4, title }: XStaticGalleryProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n entry.target.classList.add(styles.visible);\n }\n });\n },\n {\n threshold: 0.1,\n rootMargin: '0px 0px -50px 0px',\n }\n );\n\n const items = containerRef.current?.querySelectorAll(`.${styles.masonryItem}`);\n items?.forEach((el) => observer.observe(el));\n\n return () => observer.disconnect();\n }, []);\n\n const colClass = COLUMN_CLASSES[columns] || COLUMN_CLASSES[4];\n\n return (\n <div ref={containerRef} className={styles.galleryContainer}>\n {title && <h2 className={styles.galleryTitle}>{title}</h2>}\n\n <div className={`${styles.masonryGrid} ${colClass}`}>\n {images.map((image, index) => (\n <div key={index} className={styles.masonryItem}>\n <div className={styles.imageContainer}>\n <Image\n src={image.src}\n alt={image.alt}\n width={600}\n height={600}\n className={styles.galleryImage}\n loading=\"lazy\"\n sizes=\"(max-width: 640px) 100vw, (max-width: 768px) 50vw, (max-width: 1280px) 33vw, 25vw\"\n />\n <div className={styles.imageOverlay} />\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n",".galleryContainer {\n width: 100%;\n max-width: 80rem;\n margin: 0 auto;\n padding: 1rem 1rem 3rem;\n}\n\n.galleryTitle {\n font-size: 1.875rem;\n text-align: right;\n color: var(--primary);\n margin-bottom: 3rem;\n opacity: 0.8;\n}\n\n/* Masonry via CSS columns */\n.masonryGrid {\n gap: 1rem;\n}\n\n.masonryItem {\n break-inside: avoid;\n position: relative;\n border-radius: 1rem;\n overflow: hidden;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n margin-bottom: 1rem;\n opacity: 0;\n transform: translateY(20px);\n transition: opacity 0.5s ease-out, transform 0.5s ease-out, box-shadow 0.3s ease;\n}\n\n.masonryItem.visible {\n opacity: 1;\n transform: translateY(0);\n}\n\n.masonryItem:hover {\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);\n}\n\n.imageContainer {\n position: relative;\n width: 100%;\n overflow: hidden;\n border-radius: 1rem;\n}\n\n.galleryImage {\n width: 100%;\n height: auto;\n object-fit: cover;\n display: block;\n transition: transform 0.5s ease-out;\n}\n\n.masonryItem:hover .galleryImage {\n transform: scale(1.05);\n}\n\n.imageOverlay {\n position: absolute;\n inset: 0;\n background: rgba(0, 0, 0, 0);\n transition: background 0.3s ease;\n pointer-events: none;\n}\n\n.masonryItem:hover .imageOverlay {\n background: rgba(0, 0, 0, 0.1);\n}\n\n/* Column count via CSS custom property */\n.cols1 { columns: 1; }\n.cols2 { columns: 2; }\n.cols3 { columns: 3; }\n.cols4 { columns: 4; }\n.cols5 { columns: 5; }\n\n/* Responsive overrides */\n@media (max-width: 1280px) {\n .cols4, .cols5 { columns: 3; }\n}\n\n@media (max-width: 768px) {\n .cols3, .cols4, .cols5 { columns: 2; }\n}\n\n@media (max-width: 640px) {\n .cols2, .cols3, .cols4, .cols5 { columns: 1; }\n}\n"],"mappings":"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","names":["XMicroGalleryText_default","useEffect","useRef","Image","jsx","jsxs","useRef","useEffect","Image"]}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// src/components/layout/xfooter/XFooter.tsx
|
|
2
|
+
import Link from "next/link";
|
|
3
|
+
|
|
4
|
+
// src/components/layout/xfooter/XFooter.module.css
|
|
5
|
+
var XFooter_default = {};
|
|
6
|
+
|
|
7
|
+
// src/components/layout/xfooter/XFooter.tsx
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
function XFooter({
|
|
10
|
+
links,
|
|
11
|
+
copyright,
|
|
12
|
+
layout = "horizontal",
|
|
13
|
+
columns = 1,
|
|
14
|
+
colors,
|
|
15
|
+
className = ""
|
|
16
|
+
}) {
|
|
17
|
+
const customStyles = {
|
|
18
|
+
"--xf-bg": colors?.bg,
|
|
19
|
+
"--xf-text": colors?.text,
|
|
20
|
+
"--xf-accent": colors?.accent,
|
|
21
|
+
"--xf-border": colors?.border,
|
|
22
|
+
"--xf-cols": layout === "horizontal" ? columns : 1
|
|
23
|
+
};
|
|
24
|
+
const currentYear = copyright?.customYear || (/* @__PURE__ */ new Date()).getFullYear();
|
|
25
|
+
const copyLabel = copyright?.text || "Xscriptor";
|
|
26
|
+
return /* @__PURE__ */ jsx("footer", { className: `${XFooter_default.XFooter} ${className}`, style: customStyles, children: /* @__PURE__ */ jsxs("div", { className: XFooter_default.container, children: [
|
|
27
|
+
/* @__PURE__ */ jsx("nav", { className: layout === "vertical" ? XFooter_default.navVertical : XFooter_default.nav, children: links.map((link, idx) => /* @__PURE__ */ jsx(Link, { href: link.href, className: XFooter_default.link, children: link.label }, idx)) }),
|
|
28
|
+
/* @__PURE__ */ jsxs("div", { className: XFooter_default.copyright, children: [
|
|
29
|
+
"\xA9 ",
|
|
30
|
+
copyright?.yearFirst ? `${currentYear} ${copyLabel}` : `${copyLabel} ${currentYear}`
|
|
31
|
+
] })
|
|
32
|
+
] }) });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/components/layout/xseparator/XSeparator.module.css
|
|
36
|
+
var XSeparator_default = {};
|
|
37
|
+
|
|
38
|
+
// src/components/layout/xseparator/XSeparator.tsx
|
|
39
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
40
|
+
function XSeparator({
|
|
41
|
+
orientation = "horizontal",
|
|
42
|
+
variant = "solid",
|
|
43
|
+
isFaded = false,
|
|
44
|
+
hasX = false,
|
|
45
|
+
xColor,
|
|
46
|
+
xBg = "white",
|
|
47
|
+
thickness = "1px",
|
|
48
|
+
color = "#e2e8f0",
|
|
49
|
+
gap = "1rem",
|
|
50
|
+
className = ""
|
|
51
|
+
}) {
|
|
52
|
+
const dynamicStyles = {
|
|
53
|
+
"--separator-color": color,
|
|
54
|
+
"--separator-thickness": thickness,
|
|
55
|
+
"--separator-margin": gap,
|
|
56
|
+
"--x-color": xColor || color,
|
|
57
|
+
// Si no se define xColor, usa el color de la línea
|
|
58
|
+
"--x-bg": xBg
|
|
59
|
+
};
|
|
60
|
+
const classes = [
|
|
61
|
+
XSeparator_default.separator,
|
|
62
|
+
orientation === "vertical" ? XSeparator_default.vertical : XSeparator_default.horizontal,
|
|
63
|
+
variant !== "solid" && XSeparator_default[variant],
|
|
64
|
+
isFaded && XSeparator_default.faded
|
|
65
|
+
].filter(Boolean).join(" ");
|
|
66
|
+
const line = /* @__PURE__ */ jsx2("hr", { className: classes, style: dynamicStyles });
|
|
67
|
+
if (!hasX) return line;
|
|
68
|
+
return /* @__PURE__ */ jsxs2("div", { className: `${XSeparator_default.separatorContainer} ${className}`, style: dynamicStyles, children: [
|
|
69
|
+
line,
|
|
70
|
+
/* @__PURE__ */ jsx2("div", { className: XSeparator_default.iconWrapper, children: "\u2715" })
|
|
71
|
+
] });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/components/layout/xzigzaglayout/XZigZagLayout.tsx
|
|
75
|
+
import { Children, useEffect, useRef, useState, useCallback } from "react";
|
|
76
|
+
|
|
77
|
+
// src/components/layout/xzigzaglayout/XZigZagLayout.module.css
|
|
78
|
+
var XZigZagLayout_default = {};
|
|
79
|
+
|
|
80
|
+
// src/components/layout/xzigzaglayout/XZigZagLayout.tsx
|
|
81
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
82
|
+
function XZigZagLayout({
|
|
83
|
+
children,
|
|
84
|
+
className,
|
|
85
|
+
style,
|
|
86
|
+
startSide = "left",
|
|
87
|
+
gap,
|
|
88
|
+
offset,
|
|
89
|
+
textAlign = "inherit",
|
|
90
|
+
showLine = false,
|
|
91
|
+
lineColor = "#cccccc",
|
|
92
|
+
lineThickness = 2,
|
|
93
|
+
...rest
|
|
94
|
+
}) {
|
|
95
|
+
const items = Children.toArray(children).filter(Boolean);
|
|
96
|
+
const containerRef = useRef(null);
|
|
97
|
+
const itemsRef = useRef([]);
|
|
98
|
+
const pathRef = useRef(null);
|
|
99
|
+
const [points, setPoints] = useState([]);
|
|
100
|
+
const [pathLength, setPathLength] = useState(0);
|
|
101
|
+
const [drawProgress, setDrawProgress] = useState(0);
|
|
102
|
+
const calculatePoints = useCallback(() => {
|
|
103
|
+
if (!containerRef.current) return;
|
|
104
|
+
const containerRect = containerRef.current.getBoundingClientRect();
|
|
105
|
+
const newPoints = itemsRef.current.filter(Boolean).map((el) => {
|
|
106
|
+
const rect = el.getBoundingClientRect();
|
|
107
|
+
return {
|
|
108
|
+
x: rect.left + rect.width / 2 - containerRect.left,
|
|
109
|
+
y: rect.top + rect.height / 2 - containerRect.top
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
if (newPoints.length > 0) {
|
|
113
|
+
newPoints.unshift({ x: newPoints[0].x, y: 0 });
|
|
114
|
+
newPoints.push({ x: newPoints[newPoints.length - 1].x, y: containerRect.height });
|
|
115
|
+
}
|
|
116
|
+
setPoints(newPoints);
|
|
117
|
+
}, []);
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
if (!showLine || !containerRef.current) return;
|
|
120
|
+
const observer = new ResizeObserver(() => calculatePoints());
|
|
121
|
+
observer.observe(containerRef.current);
|
|
122
|
+
calculatePoints();
|
|
123
|
+
return () => observer.disconnect();
|
|
124
|
+
}, [showLine, calculatePoints]);
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
if (pathRef.current) setPathLength(pathRef.current.getTotalLength());
|
|
127
|
+
}, [points]);
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (!showLine) return;
|
|
130
|
+
const handleScroll = () => {
|
|
131
|
+
if (!containerRef.current) return;
|
|
132
|
+
const { top, height } = containerRef.current.getBoundingClientRect();
|
|
133
|
+
const windowHeight = window.innerHeight;
|
|
134
|
+
const start = windowHeight / 2;
|
|
135
|
+
const progress = (start - top) / height;
|
|
136
|
+
setDrawProgress(Math.min(Math.max(progress, 0), 1));
|
|
137
|
+
};
|
|
138
|
+
window.addEventListener("scroll", handleScroll);
|
|
139
|
+
handleScroll();
|
|
140
|
+
return () => window.removeEventListener("scroll", handleScroll);
|
|
141
|
+
}, [showLine]);
|
|
142
|
+
const cssVars = {};
|
|
143
|
+
if (gap !== void 0) cssVars["--x-zigzag-gap"] = typeof gap === "number" ? `${gap}px` : gap;
|
|
144
|
+
if (offset !== void 0) cssVars["--x-zigzag-offset"] = typeof offset === "number" ? `${offset}px` : offset;
|
|
145
|
+
const mergedStyle = { ...style, ...cssVars };
|
|
146
|
+
const pathD = points.length > 0 ? `M ${points[0].x} ${points[0].y} ` + points.slice(1).map((p) => `L ${p.x} ${p.y}`).join(" ") : "";
|
|
147
|
+
return /* @__PURE__ */ jsxs3(
|
|
148
|
+
"div",
|
|
149
|
+
{
|
|
150
|
+
ref: containerRef,
|
|
151
|
+
...rest,
|
|
152
|
+
className: [XZigZagLayout_default.layout, className].filter(Boolean).join(" "),
|
|
153
|
+
style: mergedStyle,
|
|
154
|
+
children: [
|
|
155
|
+
showLine && points.length > 0 && /* @__PURE__ */ jsx3("svg", { className: XZigZagLayout_default.svgLine, xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx3(
|
|
156
|
+
"path",
|
|
157
|
+
{
|
|
158
|
+
ref: pathRef,
|
|
159
|
+
d: pathD,
|
|
160
|
+
fill: "none",
|
|
161
|
+
stroke: lineColor,
|
|
162
|
+
strokeWidth: lineThickness,
|
|
163
|
+
strokeDasharray: pathLength,
|
|
164
|
+
strokeDashoffset: pathLength - pathLength * drawProgress,
|
|
165
|
+
style: { transition: "stroke-dashoffset 0.1s ease-out" }
|
|
166
|
+
}
|
|
167
|
+
) }),
|
|
168
|
+
items.map((child, index) => {
|
|
169
|
+
const isStartLeft = startSide === "left";
|
|
170
|
+
const alignLeft = isStartLeft ? index % 2 === 0 : index % 2 !== 0;
|
|
171
|
+
const alignmentClass = textAlign === "side" ? alignLeft ? XZigZagLayout_default.textLeft : XZigZagLayout_default.textRight : textAlign === "left" ? XZigZagLayout_default.textLeft : textAlign === "right" ? XZigZagLayout_default.textRight : "";
|
|
172
|
+
return /* @__PURE__ */ jsx3("div", { className: `${XZigZagLayout_default.item} ${alignLeft ? XZigZagLayout_default.left : XZigZagLayout_default.right} ${alignmentClass}`, children: /* @__PURE__ */ jsx3("div", { ref: (el) => {
|
|
173
|
+
itemsRef.current[index] = el;
|
|
174
|
+
}, className: XZigZagLayout_default.contentWrapper, children: child }) }, index);
|
|
175
|
+
})
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export {
|
|
182
|
+
XFooter,
|
|
183
|
+
XSeparator,
|
|
184
|
+
XZigZagLayout
|
|
185
|
+
};
|
|
186
|
+
//# sourceMappingURL=chunk-42XPBYTL.mjs.map
|