@columbia-libraries/cul-toolkit 5.0.5 → 5.1.3

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
@@ -59,3 +59,247 @@ cap dev deploy # or replace "dev" with "test" or "prod"
59
59
 
60
60
  Note: In order to deploy, you need to have your public key in the remote server user's authorized_keys file on your dev/test/prod hosts.
61
61
 
62
+
63
+ ---
64
+
65
+ ## CUL Menu Usage
66
+
67
+ CUL Menu is a portable BS5-compatible menu system that renders two styles of navigational menus from an authoritative JSON data source.
68
+
69
+ Purpose:
70
+
71
+ * **Menu content changes more often than apps**
72
+ * Avoid editing/redeploying multiple sites for a simple label or link change
73
+ * Centralized menu control
74
+ * Safe degradation when offline or blocked by CORS
75
+
76
+ Supports:
77
+
78
+ * **Runtime menu updates** (no rebuild required)
79
+ * **Graceful fallback** to a bundled example menu
80
+ * **Multiple render styles** (vertical collapse menu (CUL global menu / v5 theme), navbar (lweb v3 style))
81
+
82
+ Features:
83
+
84
+ * Fetch menu JSON from **remote authoritative source**
85
+ * Fallback to a **bundled example menu** if remote fails
86
+ * Cache-busting via app version
87
+ * Works in: Dynamic/JS apps, Static HTML pages, WP themes, etc.
88
+
89
+ Requirements:
90
+
91
+ * Bootstrap 5 CSS (**part of CUL Toolkit v5!**)
92
+ * Bootstrap 5 JS (dropdowns / collapse) (**part of CUL Toolkit v5!**)
93
+ * Modern browser (ES2019+)
94
+
95
+ ---
96
+
97
+ ### CUL Menu JSON Format
98
+
99
+ ```json
100
+ {
101
+ "Services & Tools": [
102
+ {
103
+ "href": "https://library.columbia.edu/services.html",
104
+ "value": "Services & Tools"
105
+ },
106
+ ],
107
+ "Libraries": [
108
+ {
109
+ "href": "https://library.columbia.edu/libraries.html",
110
+ "value": "Libraries & Affiliates"
111
+ },
112
+ {
113
+ "href": "https://library.columbia.edu/libraries/avery.html",
114
+ "value": "Avery Architectural & Fine Arts Library"
115
+ },
116
+ ]
117
+ }
118
+ ```
119
+
120
+ ### Usage in this app (CUL Toolkit examples, etc)
121
+
122
+ #### Environmental Variable
123
+
124
+ Create root `.env`:
125
+
126
+ ```env
127
+ VITE_CUL_MENU_URL=https://menus.example.com/cul-main-menu.json
128
+ ```
129
+
130
+ #### main.js
131
+
132
+ ```js
133
+ import { makeCULmenu } from './culmenu.js';
134
+ import { makeCULNavbarMenu } from './culmenu-navbar.js';
135
+
136
+ const MENU_URL = import.meta.env.VITE_CUL_MENU_URL || undefined;
137
+
138
+ makeCULmenu(MENU_URL);
139
+ makeCULNavbarMenu('[data-cul-navbar]', MENU_URL);
140
+ ```
141
+
142
+ ---
143
+
144
+ ### Markup
145
+
146
+ #### Vertical / Collapse Menu
147
+
148
+ ```html
149
+ <nav data-cul-menu class="cul-menu-loading"></nav>
150
+ ```
151
+
152
+ #### Navbar / Dropdown Menu
153
+
154
+ ```html
155
+ <nav
156
+ class="navbar navbar-expand-lg cul-menu-loading"
157
+ data-cul-navbar
158
+ data-menu-id="main"
159
+ >
160
+ <ul class="navbar-nav"></ul>
161
+ </nav>
162
+ ```
163
+
164
+ The JS will replace the contents at runtime.
165
+
166
+ ---
167
+
168
+ ### Loading & Fallback Behavior
169
+
170
+ 1. Attempt to fetch menu from:
171
+
172
+ * `VITE_CUL_MENU_URL` (if provided)
173
+ 2. If fetch fails:
174
+
175
+ * Use bundled example menu (`cul-main-menu.json`)
176
+ 3. Cache-busting is applied using app version
177
+
178
+ Console warning when fallback is used:
179
+
180
+ ```
181
+ [CUL Menu] Remote menu unavailable, using bundled example.
182
+ ```
183
+
184
+ ---
185
+
186
+ ### Using the Bundle on Another Site
187
+
188
+ Standalone bundle:
189
+
190
+ * `cul-menu.bundle.js` (IIFE, for `<script>` tags)
191
+ * `cul-menu.bundle.es.js` (ES module)
192
+
193
+ #### Example static HTML / IIFE usage
194
+
195
+ ```html
196
+ <link rel="stylesheet" href="https://toolkit.library.columbia.edu/v5/setup.css">
197
+
198
+ <nav data-cul-menu></nav>
199
+
200
+ <script src="https://toolkit.library.columbia.edu/v5/bundles/cul-menu.bundle.js"></script>
201
+ <script>
202
+ CULMenu.initCollapse({
203
+ url: 'https://toolkit.library.columbia.edu/v5/assets/cul-main-menu.json'
204
+ });
205
+ </script>
206
+ ```
207
+
208
+ *Note: script/JSON URLs can be local or remote or mixed.*
209
+
210
+ ---
211
+
212
+ #### ES module app usage
213
+
214
+ *Installation*
215
+
216
+ ```bash
217
+ npm install @columbia-libraries/cul-toolkit
218
+ ```
219
+
220
+ *Import and usage*
221
+
222
+ ```js
223
+ import '@columbia-libraries/cul-toolkit/styles';
224
+ import '@columbia-libraries/cul-toolkit/setup';
225
+
226
+ import { makeCULmenu } from '@columbia-libraries/cul-toolkit';
227
+
228
+ const MENU_URL =
229
+ import.meta.env.VITE_CUL_MENU_URL ||
230
+ 'https://toolkit.library.columbia.edu/v5/assets/cul-main-menu.json';
231
+
232
+ makeCULmenu(MENU_URL);
233
+ ```
234
+
235
+ *Framework Notes*
236
+
237
+ makeCULmenu(MENU_URL) manipulates DOM elements with [data-cul-menu].
238
+ It must be called after the elements exist in the DOM:
239
+
240
+ - Vue: call after app.mount() or inside onMounted() / nextTick().
241
+ - React: call inside useEffect(() => { ... }, []).
242
+
243
+ *Vue note:*
244
+ ```js
245
+ import { createApp, nextTick } from 'vue';
246
+ import App from './App.vue';
247
+ import { makeCULmenu } from '@columbia-libraries/cul-toolkit';
248
+
249
+ const app = createApp(App);
250
+
251
+ // for after app is mounted:
252
+ app.mount('#app');
253
+ nextTick(() => {
254
+ makeCULmenu(MENU_URL);
255
+ });
256
+
257
+ // or for inside a component:
258
+ onMounted(() => {
259
+ makeCULmenu(MENU_URL);
260
+ });
261
+ ```
262
+
263
+ *React/other frameworks:*
264
+
265
+ Call after the component that contains [data-my-menu] has mounted.
266
+
267
+ *Markup requirement*
268
+
269
+ Must include target element: <nav data-my-menu></nav>
270
+
271
+ ---
272
+
273
+ #### Available Globals
274
+
275
+ - CULMenu.initCollapse({ url });
276
+ - CULMenu.initNavbar({ selector, url });
277
+
278
+ ---
279
+
280
+ ### Build Output (npm package)
281
+
282
+ ```bash
283
+ dist/
284
+ ├── assets/
285
+ │   ├── columbia_crown_logo-square-135x135.svg
286
+ │   ├── cul-main-menu.json
287
+ │   ├── cul-text-logo.svg
288
+ │   ├── favicon.ico
289
+ │   ├── main.css
290
+ │   └── main.js
291
+ ├── bundles/
292
+ │   ├── cul-menu.bundle.es.js
293
+ │   ├── cul-menu.bundle.es.js.map
294
+ │   ├── cul-menu.bundle.js
295
+ │   └── cul-menu.bundle.js.map
296
+ ├── js/
297
+ │   ├── quicksearch.js
298
+ │   └── typeahead-0.11.1.bundle.min.js
299
+ ├── setup.css
300
+ └── setup.js
301
+ ```
302
+
303
+ ---
304
+
305
+
@@ -0,0 +1,242 @@
1
+ {
2
+ "Services & Tools": [
3
+ {
4
+ "href": "https://library.columbia.edu/services.html",
5
+ "value": "Services & Tools"
6
+ },
7
+ {
8
+ "href": "https://library.columbia.edu/services/faq.html",
9
+ "value": "FAQ"
10
+ },
11
+ {
12
+ "href": "https://library.columbia.edu/using-libraries/alumni.html",
13
+ "value": "For Alumni"
14
+ },
15
+ {
16
+ "href": "https://library.columbia.edu/services/faculty.html",
17
+ "value": "For Faculty"
18
+ },
19
+ {
20
+ "href": "https://library.columbia.edu/services.html#audience=student",
21
+ "value": "For Students"
22
+ },
23
+ {
24
+ "href": "https://library.columbia.edu/using-libraries/visitors.html",
25
+ "value": "For Visitors"
26
+ }
27
+ ],
28
+ "Libraries": [
29
+ {
30
+ "href": "https://library.columbia.edu/libraries.html",
31
+ "value": "Libraries & Affiliates"
32
+ },
33
+ {
34
+ "href": "https://library.columbia.edu/libraries/avery.html",
35
+ "value": "Avery Architectural & Fine Arts Library"
36
+ },
37
+ {
38
+ "href": "https://library.columbia.edu/libraries/burke.html",
39
+ "value": "Burke Library at Union Theological Seminary"
40
+ },
41
+ {
42
+ "href": "https://library.columbia.edu/libraries/business.html",
43
+ "value": "Business & Economics Library in Uris"
44
+ },
45
+ {
46
+ "href": "https://library.columbia.edu/libraries/business-manhattanville.html",
47
+ "value": "Business Library at Manhattanville"
48
+ },
49
+ {
50
+ "href": "https://library.columbia.edu/libraries/butler.html",
51
+ "value": "Butler Library"
52
+ },
53
+ {
54
+ "href": "https://library.columbia.edu/libraries/eastasian.html",
55
+ "value": "C.V. Starr East Asian Library"
56
+ },
57
+ {
58
+ "href": "https://library.columbia.edu/libraries/music.html",
59
+ "value": "Gabe M. Wiener Music & Arts Library"
60
+ },
61
+ {
62
+ "href": "https://library.cumc.columbia.edu/",
63
+ "value": "Health Sciences Library"
64
+ },
65
+ {
66
+ "href": "https://library.columbia.edu/libraries/journalism.html",
67
+ "value": "Journalism Library"
68
+ },
69
+ {
70
+ "href": "https://library.columbia.edu/libraries/lehman.html",
71
+ "value": "Lehman Social Sciences Library"
72
+ },
73
+ {
74
+ "href": "http://www.law.columbia.edu/library/",
75
+ "value": "Li Lu Law Library"
76
+ },
77
+ {
78
+ "href": "https://library.columbia.edu/libraries/math.html",
79
+ "value": "Mathematics Library"
80
+ },
81
+ {
82
+ "href": "https://library.columbia.edu/libraries/undergraduate.html",
83
+ "value": "Milstein Undergraduate Library"
84
+ },
85
+ {
86
+ "href": "https://library.columbia.edu/libraries/rbml.html",
87
+ "value": "Rare Book & Manuscript Library"
88
+ },
89
+ {
90
+ "href": "https://library.columbia.edu/libraries/science-engineering.html",
91
+ "value": "Science & Engineering Library"
92
+ },
93
+ {
94
+ "href": "https://library.columbia.edu/libraries/social-work.html",
95
+ "value": "Social Work Library"
96
+ }
97
+ ],
98
+ "Collections": [
99
+ {
100
+ "href": "https://library.columbia.edu/collections.html",
101
+ "value": "About Our Collections"
102
+ },
103
+ {
104
+ "href": "https://academiccommons.columbia.edu/",
105
+ "value": "Academic Commons"
106
+ },
107
+ {
108
+ "href": "https://library.columbia.edu/collections/archives-portal.html",
109
+ "value": "Archival Collections"
110
+ },
111
+ {
112
+ "href": "https://resolver.library.columbia.edu/clio",
113
+ "value": "CLIO: Columbia Libraries Catalog"
114
+ },
115
+ {
116
+ "href": "https://library.columbia.edu/about/policies/collection-development.html",
117
+ "value": "Collection Development"
118
+ },
119
+ {
120
+ "href": "https://library.columbia.edu/collections/digital-collections.html",
121
+ "value": "Digital Collections & Exhibitions"
122
+ },
123
+ {
124
+ "href": "https://library.columbia.edu/collections/eresources.html",
125
+ "value": "E-Resources"
126
+ },
127
+ {
128
+ "href": "https://library.columbia.edu/collections/oral-history-portal.html",
129
+ "value": "Oral History Collections"
130
+ },
131
+ {
132
+ "href": "https://resolver.library.columbia.edu/lweb0004",
133
+ "value": "Recommend a Title for Purchase"
134
+ },
135
+ {
136
+ "href": "https://library.columbia.edu/about/policies/collection-development/repatriation-return.html",
137
+ "value": "Repatriation"
138
+ },
139
+ {
140
+ "href": "https://library.columbia.edu/about/staff/subject-specialists-by-subject.html",
141
+ "value": "Subject Specialists"
142
+ }
143
+ ],
144
+ "Using the Libraries": [
145
+ {
146
+ "href": "https://library.columbia.edu/using-libraries.html",
147
+ "value": "Using the Libraries"
148
+ },
149
+ {
150
+ "href": "https://library.columbia.edu/using-libraries/access-privileges.html",
151
+ "value": "Access Privileges"
152
+ },
153
+ {
154
+ "href": "https://library.columbia.edu/using-libraries/disability.html",
155
+ "value": "Accessibility"
156
+ },
157
+ {
158
+ "href": "https://library.columbia.edu/using-libraries/borrowing.html",
159
+ "value": "Borrow, Request, Renew"
160
+ },
161
+ {
162
+ "href": "https://library.columbia.edu/services/reserves.html",
163
+ "value": "Course Reserves"
164
+ },
165
+ {
166
+ "href": "https://hours.library.columbia.edu/",
167
+ "value": "Hours"
168
+ },
169
+ {
170
+ "href": "https://library.columbia.edu/using-libraries/printing.html",
171
+ "value": "Print, Scan, Digitize"
172
+ }
173
+ ],
174
+ "Research & Teaching": [
175
+ {
176
+ "href": "https://library.columbia.edu/research-teaching.html",
177
+ "value": "Research & Teaching"
178
+ },
179
+ {
180
+ "href": "https://copyright.columbia.edu/index.html",
181
+ "value": "Copyright Advisory Services"
182
+ },
183
+ {
184
+ "href": "https://library.columbia.edu/research-teaching/getting-started.html",
185
+ "value": "Getting Started with the Libraries"
186
+ },
187
+ {
188
+ "href": "https://library.columbia.edu/research-teaching/open-scholarship.html",
189
+ "value": "Open Scholarship Services"
190
+ },
191
+ {
192
+ "href": "https://library.columbia.edu/services/research-data-services.html",
193
+ "value": "Research Data Services"
194
+ },
195
+ {
196
+ "href": "https://library.columbia.edu/services/subject-guides.html",
197
+ "value": "Subject & Course Guides"
198
+ },
199
+ {
200
+ "href": "https://library.columbia.edu/research-teaching/workshops.html",
201
+ "value": "Workshops & Training"
202
+ }
203
+ ],
204
+ "About": [
205
+ {
206
+ "href": "https://library.columbia.edu/about.html",
207
+ "value": "About the Libraries"
208
+ },
209
+ {
210
+ "href": "https://library.columbia.edu/about/jobs-internships.html",
211
+ "value": "Jobs & Internships"
212
+ },
213
+ {
214
+ "href": "https://library.columbia.edu/about/news/alert.html",
215
+ "value": "Library Status Updates"
216
+ },
217
+ {
218
+ "href": "https://library.columbia.edu/about/news.html",
219
+ "value": "News"
220
+ },
221
+ {
222
+ "href": "https://library.columbia.edu/about/values.html",
223
+ "value": "Our Values & Commitment in Action"
224
+ },
225
+ {
226
+ "href": "https://library.columbia.edu/about/policies.html",
227
+ "value": "Policies"
228
+ },
229
+ {
230
+ "href": "https://library.columbia.edu/about/staff.html",
231
+ "value": "Staff"
232
+ },
233
+ {
234
+ "href": "https://strategicdirections.library.columbia.edu/",
235
+ "value": "Strategic Directions"
236
+ },
237
+ {
238
+ "href": "https://library.columbia.edu/about/student_advisory_committee.html",
239
+ "value": "Student Library Advisory Committee"
240
+ }
241
+ ]
242
+ }