@bailaya/react 1.0.13 → 1.0.15
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
CHANGED
|
@@ -6,39 +6,37 @@
|
|
|
6
6
|
|
|
7
7
|
`@bailaya/react` builds on top of **@bailaya/core** to provide:
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
* A **`BailayaProvider`** + **`useBailayaClient`** context
|
|
10
|
+
* React **hooks** for fetching all core data (with `loading`, `error`, `data`, and `refetch`)
|
|
11
|
+
* **Components** with sensible Tailwind defaults (and full styling slots)
|
|
12
|
+
* Full TypeScript support, including localized text & date formatting
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
> Works **with or without Tailwind**. If you don’t use Tailwind, just override the class props (or use the render props) to apply your own styling.
|
|
15
15
|
|
|
16
16
|
## Features
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- Date formatting via Intl
|
|
35
|
-
- Custom text labels
|
|
18
|
+
* **Context + client** (`BailayaProvider` + `useBailayaClient`)
|
|
19
|
+
* **Hooks** (all return `{ data, error, loading, refetch }`)
|
|
20
|
+
|
|
21
|
+
* `useStudioProfile(overrideId?)`
|
|
22
|
+
* `useUserProfile(userId)`
|
|
23
|
+
* `useInstructors(overrideId?)`
|
|
24
|
+
* `useClasses(from?, overrideId?)`
|
|
25
|
+
* `useClassesByType(typeName, from?, overrideId?)`
|
|
26
|
+
* **Components** (all props overridable)
|
|
27
|
+
|
|
28
|
+
* `<StudioProfileCard />`
|
|
29
|
+
* `<UserProfileCard />`
|
|
30
|
+
* `<InstructorList />`
|
|
31
|
+
* `<ClassSchedule />`
|
|
32
|
+
* `<ClassScheduleByType />`
|
|
33
|
+
* `<StudioDescription />`
|
|
36
34
|
|
|
37
35
|
## Installation
|
|
38
36
|
|
|
39
37
|
```bash
|
|
40
38
|
npm install @bailaya/react
|
|
41
|
-
|
|
39
|
+
```
|
|
42
40
|
|
|
43
41
|
or with Yarn:
|
|
44
42
|
|
|
@@ -51,6 +49,52 @@ yarn add @bailaya/react
|
|
|
51
49
|
> * `"react": ">=17"`
|
|
52
50
|
> * `"react-dom": ">=17"`
|
|
53
51
|
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Tailwind Setup (optional)
|
|
55
|
+
|
|
56
|
+
If your app uses Tailwind, add this glob so JIT scans our package classes:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
// tailwind.config.js or tailwind.config.ts
|
|
60
|
+
module.exports = {
|
|
61
|
+
content: [
|
|
62
|
+
'./node_modules/@bailaya/**/*.{js,mjs,ts,tsx}',
|
|
63
|
+
],
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
> If you’re not using Tailwind, skip this section.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Styling without Tailwind
|
|
72
|
+
|
|
73
|
+
You can use all components in non-Tailwind projects:
|
|
74
|
+
|
|
75
|
+
* Pass your own `className`/`*ClassName` props to inject your CSS classes.
|
|
76
|
+
* Or use `renderItem` / `renderProfile` props to fully control markup.
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import { InstructorList } from '@bailaya/react'
|
|
80
|
+
|
|
81
|
+
export function Team() {
|
|
82
|
+
return (
|
|
83
|
+
<InstructorList
|
|
84
|
+
className="team"
|
|
85
|
+
itemClassName="card"
|
|
86
|
+
imageWrapperClassName="avatarWrap"
|
|
87
|
+
imageClassName="avatar"
|
|
88
|
+
bodyClassName="cardBody"
|
|
89
|
+
nameClassName="cardTitle"
|
|
90
|
+
bioClassName="cardText"
|
|
91
|
+
/>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
54
98
|
## Quick Start
|
|
55
99
|
|
|
56
100
|
First, wrap your app with **BailayaProvider**:
|
|
@@ -69,8 +113,6 @@ export default function App() {
|
|
|
69
113
|
}
|
|
70
114
|
```
|
|
71
115
|
|
|
72
|
-
---
|
|
73
|
-
|
|
74
116
|
### Using a Hook
|
|
75
117
|
|
|
76
118
|
```tsx
|
|
@@ -96,8 +138,6 @@ export function TeamSection() {
|
|
|
96
138
|
}
|
|
97
139
|
```
|
|
98
140
|
|
|
99
|
-
---
|
|
100
|
-
|
|
101
141
|
### Using a Component
|
|
102
142
|
|
|
103
143
|
```tsx
|
|
@@ -107,10 +147,7 @@ import { StudioProfileCard } from "@bailaya/react";
|
|
|
107
147
|
export function Dashboard() {
|
|
108
148
|
return (
|
|
109
149
|
<div className="max-w-md mx-auto">
|
|
110
|
-
<StudioProfileCard
|
|
111
|
-
locale="en"
|
|
112
|
-
className="bg-white rounded-lg shadow p-6"
|
|
113
|
-
/>
|
|
150
|
+
<StudioProfileCard locale="en" />
|
|
114
151
|
</div>
|
|
115
152
|
);
|
|
116
153
|
}
|
|
@@ -3,7 +3,7 @@ import type { Instructor } from '@bailaya/core';
|
|
|
3
3
|
export interface InstructorListProps {
|
|
4
4
|
/** Optional studio ID to override the default configured ID */
|
|
5
5
|
overrideId?: string;
|
|
6
|
-
/** Locale code (e.g., "en", "es") for picking the
|
|
6
|
+
/** Locale code (e.g., "en", "es") for picking the bio */
|
|
7
7
|
locale?: string;
|
|
8
8
|
/** Root container wrapper */
|
|
9
9
|
className?: string;
|
|
@@ -17,7 +17,7 @@ export interface InstructorListProps {
|
|
|
17
17
|
bodyClassName?: string;
|
|
18
18
|
/** Instructor name heading */
|
|
19
19
|
nameClassName?: string;
|
|
20
|
-
/** Instructor bio paragraph
|
|
20
|
+
/** Instructor bio paragraph */
|
|
21
21
|
bioClassName?: string;
|
|
22
22
|
/**
|
|
23
23
|
* Optional custom render function for each instructor.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstructorList.d.ts","sourceRoot":"","sources":["../../src/components/InstructorList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,MAAM,WAAW,mBAAmB;IAChC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,
|
|
1
|
+
{"version":3,"file":"InstructorList.d.ts","sourceRoot":"","sources":["../../src/components/InstructorList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,MAAM,WAAW,mBAAmB;IAChC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,qCAAqC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,+BAA+B;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B,iCAAiC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,KAAK,CAAC,SAAS,CAAC;CACvD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAqDxD,CAAC"}
|
|
@@ -17,11 +17,13 @@ const LoadingIcon_1 = require("./ui/LoadingIcon");
|
|
|
17
17
|
*/
|
|
18
18
|
const InstructorList = ({ overrideId, locale, className = 'mt-6 md:mt-12 space-y-8', itemClassName = 'flex flex-col md:flex-row items-center rounded-lg border border-[#DCDCDC] shadow-lg overflow-hidden', imageWrapperClassName = 'w-full p-4 pb-0 md:pb-4 md:w-1/3 aspect-square', imageClassName = 'w-full h-full rounded-xl object-cover', bodyClassName = 'p-6 flex-1 text-left', nameClassName = 'text-xl md:text-3xl font-geologica font-semibold text-[#2A2343]', bioClassName = 'mt-2 text-xs md:text-xl font-sourcesans font-semibold text-[#464646]', renderItem, }) => {
|
|
19
19
|
const { data: instructors, loading: isLoading, error } = (0, useInstructors_1.useInstructors)(overrideId);
|
|
20
|
-
if (isLoading)
|
|
20
|
+
if (isLoading) {
|
|
21
21
|
return react_1.default.createElement("div", { className: className },
|
|
22
22
|
react_1.default.createElement(LoadingIcon_1.LoadingIcon, null));
|
|
23
|
-
|
|
23
|
+
}
|
|
24
|
+
if (error) {
|
|
24
25
|
return react_1.default.createElement("div", { className: className }, error.message);
|
|
26
|
+
}
|
|
25
27
|
return (react_1.default.createElement("div", { className: className }, instructors === null || instructors === void 0 ? void 0 : instructors.map((instr) => {
|
|
26
28
|
var _a;
|
|
27
29
|
return renderItem ? (renderItem(instr)) : (react_1.default.createElement("div", { key: instr.id, className: itemClassName },
|
|
@@ -31,24 +33,10 @@ const InstructorList = ({ overrideId, locale, className = 'mt-6 md:mt-12 space-y
|
|
|
31
33
|
react_1.default.createElement("h3", { className: nameClassName },
|
|
32
34
|
instr.name,
|
|
33
35
|
instr.lastname ? ` ${instr.lastname}` : ''),
|
|
34
|
-
|
|
36
|
+
instr.bio && (react_1.default.createElement("p", { className: bioClassName }, pickLocalizedText(instr.bio, locale))))));
|
|
35
37
|
})));
|
|
36
38
|
};
|
|
37
39
|
exports.InstructorList = InstructorList;
|
|
38
|
-
/** Safely render localized bio as multiple <p> paragraphs. */
|
|
39
|
-
function renderBioParagraphs(bio, locale, bioClassName) {
|
|
40
|
-
const text = pickLocalizedText(bio, locale);
|
|
41
|
-
if (!text)
|
|
42
|
-
return null;
|
|
43
|
-
const lines = splitMultiline(text);
|
|
44
|
-
if (lines.length === 0)
|
|
45
|
-
return null;
|
|
46
|
-
// Keep the original classes on the first paragraph.
|
|
47
|
-
const firstClass = bioClassName;
|
|
48
|
-
// For subsequent paragraphs, remove any mt-* to avoid stacking big gaps.
|
|
49
|
-
const restClass = bioClassName.replace(/\bmt-\d+\b/g, '').trim() || bioClassName;
|
|
50
|
-
return (react_1.default.createElement(react_1.default.Fragment, null, lines.map((line, i) => (react_1.default.createElement("p", { key: i, className: i === 0 ? firstClass : restClass }, line)))));
|
|
51
|
-
}
|
|
52
40
|
/** Pick localized text with fallback to first available. */
|
|
53
41
|
function pickLocalizedText(map, locale) {
|
|
54
42
|
const obj = map !== null && map !== void 0 ? map : {};
|
|
@@ -57,13 +45,3 @@ function pickLocalizedText(map, locale) {
|
|
|
57
45
|
const keys = Object.keys(obj);
|
|
58
46
|
return keys.length ? obj[keys[0]] : '';
|
|
59
47
|
}
|
|
60
|
-
/** Convert <br> -> newlines, then split, trim, and filter empty lines */
|
|
61
|
-
function splitMultiline(text) {
|
|
62
|
-
if (!text)
|
|
63
|
-
return [];
|
|
64
|
-
const normalized = text.replace(/<br\s*\/?>/gi, '\n');
|
|
65
|
-
return normalized
|
|
66
|
-
.split(/\r?\n/)
|
|
67
|
-
.map((l) => l.trim())
|
|
68
|
-
.filter(Boolean);
|
|
69
|
-
}
|