Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
4cd799a
Update .gitignore to include new documentation files for UX audit and…
AkaKwak May 1, 2026
831a482
Refactor pages and update content for clarity and consistency
AkaKwak May 1, 2026
dc71d89
Remove outdated internal documentation files for UX audit and todo list
AkaKwak May 1, 2026
a0e1d38
Update location details across multiple pages to reflect new address
AkaKwak May 1, 2026
ae79e0c
Enhance map integration and animations for improved user experience
AkaKwak May 1, 2026
c3dec3c
feat(contact): creative_hosting slug, i18n mail subjects
AkaKwak May 1, 2026
fe5d3aa
ux(become_member): consolidate hero + pricing card
AkaKwak May 1, 2026
404ef87
refactor(pages): update content for clarity and consistency
AkaKwak May 1, 2026
33eb4c5
refactor(pages): enhance FAQ content and layout for better user exper…
AkaKwak May 1, 2026
02b55ee
feat(blogs, events): update authentication handling for specific actions
AkaKwak May 1, 2026
c33b34c
refactor(home, footer, opening_hours): enhance layout and content for…
AkaKwak May 1, 2026
a97cbe5
feat(website): carousels, partners content, contact layout
AkaKwak May 1, 2026
6890af1
perf(views): lazy-load secondary images
AkaKwak May 1, 2026
c58ae2e
fix(nav): horizontal menu from min-width 844px
AkaKwak May 1, 2026
bb3737c
fix(footer): balance links and newsletter mid-mobile
AkaKwak May 1, 2026
f06f69e
fix(css): add brand-accent /72 and /45 utilities for builds
AkaKwak May 1, 2026
925207b
fix(nav): padding, nowrap row, and desktop link sizing
AkaKwak May 1, 2026
c76ea6e
feat(a11y): scroll hint accent styling and aria label i18n
AkaKwak May 1, 2026
9f15e05
feat(home): hero stack, branded CTA hover, scroll arrow offset
AkaKwak May 1, 2026
a30f0c8
refactor(contacts): improve readability of recipient email assignment
AkaKwak May 1, 2026
54a0731
refactor(association): update header and article IDs for improved acc…
AkaKwak May 1, 2026
df74b9a
feat(dev,auth): quick login, safe redirects, session login flow
AkaKwak May 1, 2026
a34c14b
feat(profile): membership states, shortcuts, French role labels
AkaKwak May 1, 2026
615ce7c
Remove dev quick login and unify account UI on profile
AkaKwak May 1, 2026
c9a5571
Enhance session handling in authentication concern
AkaKwak May 1, 2026
acadc9e
test(rspec): enforce test environment in rails helper
AkaKwak May 1, 2026
c7c28cd
feat(dev): log critical auth and database incidents
AkaKwak May 1, 2026
a15db17
fix(auth): invalidate orphaned sessions and clear archived user sessions
AkaKwak May 1, 2026
2ae7482
fix(test): ignore DATABASE_URL so specs use tmp/test.sqlite3
AkaKwak May 1, 2026
7d721dd
feat(profile): embedded account/contact panels with Turbo refresh
AkaKwak May 1, 2026
8c7177a
feat(dev): reliable seed reset and local DB recovery helpers
AkaKwak May 1, 2026
bde2322
feat(profile): Modifier → Accepter flow with recap modal
AkaKwak May 1, 2026
2a4660d
fix(profile): edit first, then preview modal before save
AkaKwak May 1, 2026
2d1e6ea
feat(profile): header Modifier/Annuler/Accepter with preview-then-save
AkaKwak May 1, 2026
5cca7af
Fix profile section buttons: avoid Tailwind hidden/display conflicts
AkaKwak May 1, 2026
559fe8f
Apply section-edit button wrappers to contact coordinates header
AkaKwak May 1, 2026
fb1746c
feat(settings): require email verification before changing address
AkaKwak May 1, 2026
5f224b2
feat(settings): add email-change verification and newsletter param pa…
AkaKwak May 1, 2026
0099260
refactor(services): standardize service messaging and tighten specs
AkaKwak May 1, 2026
cf88301
refactor(profile): extract membership card helper and partial panels
AkaKwak May 1, 2026
f21edad
refactor(admin-users): isolate person identifier parsing helpers
AkaKwak May 1, 2026
6753534
refactor(admin-users): extract view adapter for person-only records
AkaKwak May 1, 2026
71a20ea
refactor(admin-users): reduce show duplication and lock person-only v…
AkaKwak May 1, 2026
1e70da3
refactor(admin-subscription-plans): isolate legacy formula id fallback
AkaKwak May 1, 2026
82c3b04
feat(routes): add canonical admin contribution_formulas routes
AkaKwak May 1, 2026
f9d6291
test(admin-routes): lock canonical contribution formulas route compat…
AkaKwak May 1, 2026
858d085
refactor(admin-ui): move inline admin scripts to Stimulus controllers
AkaKwak May 1, 2026
0c3d8ab
refactor(admin-domain): align contribution routes and member number p…
AkaKwak May 1, 2026
699e856
refactor(identity): centralize email normalization and payload defaults
AkaKwak May 1, 2026
beefae8
refactor(vocab): complete subscription→contribution vocabulary migration
AkaKwak May 1, 2026
f8d67c2
chore(todo): track todo.md in git + sort open items by speed
AkaKwak May 1, 2026
a58affe
chore(todo): update todo.md with new status and vocabulary notes
AkaKwak May 1, 2026
ca290ca
fix(ui): show all payment lines in user tab, remove dead user_id brea…
AkaKwak May 1, 2026
7eaf599
Clean admin flows and payment services
AkaKwak May 1, 2026
a3cf6a7
Remove newsletter_subscribed column from people table and migrate exi…
AkaKwak May 1, 2026
69c6a61
Remove unused ActionButtonsComponent and related membership upgrade l…
AkaKwak May 1, 2026
79cb1a0
feat(payments): persist offer audit data and align anonymization
AkaKwak May 1, 2026
3e6125d
feat(integrity): enforce contribution invariants and report anomalies
AkaKwak May 1, 2026
62959a7
refactor(admin): simplify membership, donation and contribution flows
AkaKwak May 1, 2026
4a2ad36
refactor(users): slim admin user flows and remove dead person wrappers
AkaKwak May 1, 2026
5313508
docs: sync knowledge base and test runner behavior
AkaKwak May 1, 2026
c954ee6
test(memberships): cover upgrader offer and donation lines
AkaKwak May 1, 2026
786dc6c
test(contributions): cover donations, offers and prorata credit
AkaKwak May 1, 2026
117c749
refactor(person): remove legacy creation wrappers
AkaKwak May 1, 2026
c0eda6a
test(harness): stabilize rspec sqlite isolation
AkaKwak May 2, 2026
de25bcc
test(tooling): serialize local rspec entrypoints
AkaKwak May 2, 2026
d36651d
ci(testing): align workflows with project test binaries
AkaKwak May 2, 2026
cb68d72
test(payment_line): speed up model specs and factories
AkaKwak May 2, 2026
c7d4254
test(payment): cut model-spec setup cost
AkaKwak May 2, 2026
7d4f36a
feat(development): add guard-rspec gem for improved test automation
AkaKwak May 2, 2026
c218d0b
admin(shared): add person context helpers and refresh labels
AkaKwak May 2, 2026
98533d3
contributions(checkout): streamline person purchase flow
AkaKwak May 2, 2026
d8d5c88
memberships(upgrade): clarify circus upgrade rules
AkaKwak May 2, 2026
ea28e28
payments(testing): unify recorder flow and expand request coverage
AkaKwak May 2, 2026
42628b7
pricing(rate_kind): centralize rate-kind rules in models
AkaKwak May 2, 2026
251fc89
admin(memberships): expose rate kind in membership flows
AkaKwak May 2, 2026
ceb18c7
admin(contributions): surface rate kind in formula catalog
AkaKwak May 2, 2026
8f5ef60
test(payments): cover label normalization and recorder defaults
AkaKwak May 2, 2026
07b0569
refactor(seeds): enhance seed structure and add membership logic
May 2, 2026
84b9636
chore(testing): raise coverage floor and tighten frontend loading
May 4, 2026
52c8882
feat(admin): replace subscription flows with contribution formulas
May 4, 2026
fd528b1
docs(domain): align contribution terminology and testing guide
May 4, 2026
951e012
refactor(seeds): enhance seed structure and add membership logic
May 2, 2026
cec30d1
merge
May 4, 2026
23124e4
chore(testing): raise coverage floor and tighten frontend loading
May 4, 2026
1f1c2e6
feat(memberships): add contribution options view for admin
AkaKwak May 4, 2026
f759038
Merge origin/website/sliced into website/sliced
AkaKwak May 4, 2026
8bd676c
fix(admin): improve user loading and error handling in users_controller
AkaKwak May 4, 2026
8e763e9
WIP: local UI/CSS adjustments on admin and public views
May 4, 2026
6913102
Merge branch 'wip/sliced-ui-local-may2026' into website/sliced
May 4, 2026
d988ea4
fix(spec): remove trailing whitespace in membership_card_helper_spec
AkaKwak May 4, 2026
46dd756
fix(spec): isolate session rate limit cache and assert session_id cookie
AkaKwak May 4, 2026
c40a7f3
fix(spec): clear Rails.cache before each example for rate limit isola…
AkaKwak May 4, 2026
126b75f
refactor(ui): consolidate public and admin layout primitives
May 4, 2026
2561e60
docs(todo): align internal backlog with current code
May 4, 2026
ab60664
chore(ci): update test suite configuration to include coverage and cr…
AkaKwak May 4, 2026
36b5b9d
feat(person): add account claims association and enhance account merg…
AkaKwak May 4, 2026
9b0de22
chore(database): prevent seeding in test environment to ensure isolation
AkaKwak May 4, 2026
a6604fd
chore(ci): update Docker actions and remove obsolete test workflow
AkaKwak May 4, 2026
ff7e73c
chore(ci): introduce new CI workflow for dev branch and remove obsole…
AkaKwak May 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,5 @@ SCRATCH.md

# Watchman (not used - we use Tailwind watcher instead)
/watchman
docs/internal/ux_audit_2025_01.md
docs/internal/todo.md
28 changes: 28 additions & 0 deletions app/assets/tailwind/application.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@

@import "tailwindcss";

/*
* Leaflet CSS is loaded via <link> in layouts/application.html.erb (before tailwind.css).
* Embedding @import url(leaflet) here breaks Tailwind v4 output: "@import must precede @layer".
*
* Preflight img { max-width: 100% } breaks tiles — reset inside maps only.
*/
.leaflet-container img {
max-width: none !important;
}

.leaflet-map-shell {
position: relative;
}

/* Force full bleed inside the rounded shell (Leaflet defaults + % heights are fragile). */
.leaflet-map-shell-inner.leaflet-container {
position: absolute !important;
inset: 0 !important;
width: 100% !important;
height: 100% !important;
outline: none;
}

@import "./components/buttons.css";
@import "./components/forms.css";
@import "./components/hero.css";
Expand Down Expand Up @@ -76,6 +99,8 @@
html {
@apply h-full;
overflow-y: auto;
/* Réserve l’espace scrollbar + évite le collage au bord droit (nav, etc.) */
scrollbar-gutter: stable;
}

html::-webkit-scrollbar {
Expand Down Expand Up @@ -117,8 +142,11 @@
.text-brand-accent { color: #5836A5; }
.bg-brand-accent { background-color: #5836A5; }
.bg-brand-accent\/10 { background-color: rgba(88, 54, 165, 0.1); }
/* Opacity variants used in markup; not always emitted by Tailwind v4 scan */
.bg-brand-accent\/72 { background-color: rgba(88, 54, 165, 0.72); }
.border-brand-accent { border-color: #5836A5; }
.border-brand-accent\/20 { border-color: rgba(88, 54, 165, 0.2); }
.border-brand-accent\/45 { border-color: rgba(88, 54, 165, 0.45); }

.focus-visible\:outline-brand-primary:focus-visible { outline-color: #1F5C55; }
.focus-visible\:outline-brand-accent:focus-visible { outline-color: #5836A5; }
Expand Down
3 changes: 2 additions & 1 deletion app/assets/tailwind/components/swiper_overrides.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
display: block;
}

/* Horizontal carousels need horizontal pan; pan-y blocked swipe on touch devices */
.swiper-horizontal {
touch-action: pan-y;
touch-action: pan-x pinch-zoom;
Comment thread
AkaKwak marked this conversation as resolved.
Outdated
}

.swiper-button-next,
Expand Down
1 change: 1 addition & 0 deletions app/controllers/blogs_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

class BlogsController < ApplicationController
skip_before_action :require_authentication, only: %i[latest]
before_action :set_blog, only: %i[show]

# def article
Expand Down
25 changes: 17 additions & 8 deletions app/controllers/contacts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ class ContactsController < ApplicationController
allow_unauthenticated_access only: :create

CONTACT_SUBMISSION_KEYS = %i[name email message category].freeze
LEGACY_CONTACT_CATEGORY_TO_CANONICAL = {
"residence" => "creative_hosting"
}.freeze

def create
@contact = contact_submission_params
Expand All @@ -13,23 +16,24 @@ def create
return
end

recipient_email = case @contact[:category]
when "technical"
category = canonical_contact_category(@contact[:category])
recipient_email = case category
when "technical"
ENV.fetch("CONTACT_EMAIL_TECHNICAL", nil)
when "residence"
ENV.fetch("CONTACT_EMAIL_RESIDENCE", nil)
when "partnership"
when "creative_hosting"
ENV.fetch("CONTACT_EMAIL_CREATIVE_HOSTING", nil) || ENV.fetch("CONTACT_EMAIL_RESIDENCE", nil)
when "partnership"
ENV.fetch("CONTACT_EMAIL_PARTNERSHIP", nil)
else
else
ENV.fetch("CONTACT_EMAIL_GENERAL", nil)
end
end

begin
UserMailer.contact_email(
@contact[:name],
@contact[:email],
@contact[:message],
@contact[:category],
category,
recipient_email
).deliver_later

Expand All @@ -50,6 +54,11 @@ def create

private

def canonical_contact_category(raw)
key = raw.to_s
LEGACY_CONTACT_CATEGORY_TO_CANONICAL.fetch(key, key)
end

# Formulaire public : champs à la racine (`name`, `email`, …), pas `contact[...]`.
# Toujours inclure les clés requises : `permit` seul omet les paramètres absents, ce qui faisait
# passer des requêtes incomplètes jusqu’au mailer.
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/events_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

class EventsController < ApplicationController
skip_before_action :require_authentication, only: %i[index show upcoming]
skip_before_action :require_authentication, only: %i[index show upcoming past]

def index
redirect_to page_path("news", anchor: "evenements")
Expand Down
74 changes: 61 additions & 13 deletions app/controllers/pages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ def show

if params[:id] == "contact_us"
@contact = {}
@faqs = contact_faq_entries
end

@adhesion_faqs = adhesion_faq_entries if params[:id] == "become_member"
Expand All @@ -60,29 +59,78 @@ def show
private

def contact_faq_entries
cf = page_path("contact_us", anchor: "contact-form")
lc = "text-[#5836A5] underline hover:text-[#412886]"
[
{ question: "Comment adhérer au Circographe ?", answer: "Passe sur un créneau d'ouverture : on remplit la fiche ensemble et on t'explique le fonctionnement." },
{ question: "Puis-je réserver un créneau de résidence ?", answer: "Oui, écris-nous via la catégorie 'Résidence'. Nous te recontacterons avec les disponibilités et modalités." },
{ question: "Le lieu est-il accessible aux débutant·es ?", answer: "Les entraînements libres sont destinés aux personnes autonomes. Pour débuter, on recommande une école partenaire : contacte-nous pour des conseils." },
{ question: "Proposez-vous des prestations ou des partenariats ?", answer: "Oui, nous travaillons avec des structures culturelles, établissements scolaires et entreprises. Sélectionne la catégorie 'Partenariat' pour en discuter." }
{
question: "Demander un temps d’accueil en création",
answer_html: helpers.safe_join([
"Écris-nous avec le ",
helpers.link_to("formulaire Contact", cf, class: lc),
", catégorie « Temps d’accueil en création » — on te répond sur les dispo et le cadre."
])
},
{
question: "Partenariat, atelier, événement ou projet avec le lieu",
answer_html: helpers.safe_join([
"Le plus simple : passer lors d’un créneau d’ouverture avec ton idée. Tu peux aussi utiliser le ",
helpers.link_to("formulaire Contact", cf, class: lc),
" (Partenariat ou Question générale). Les bénévoles t’orientent."
])
}
]
end

def adhesion_faq_entries
cf = page_path("contact_us", anchor: "contact-form")
lc = "text-[#5836A5] underline hover:text-[#412886]"
[
{ question: "Puis-je adhérer en ligne ?", answer: "L'inscription se fait uniquement sur place afin de te présenter le lieu et les règles d'autogestion." },
{ question: "Quels moyens de paiement acceptez-vous ?", answer: "Carte bancaire et espèces. Une adhésion de soutien peut également être effectuée par virement sur demande." },
{ question: "Faut-il être autonome pour les entraînements libres ?", answer: "Oui, les créneaux libres s'adressent aux pratiquant·es autonomes. Pour débuter, on peut te recommander des écoles partenaires." },
{ question: "Puis-je proposer un atelier ou un événement ?", answer: "Tout est possible ! Passe nous voir avec ton idée, on regardera ensemble comment l'inscrire dans la programmation." }
{
question: "Comment adhérer ?",
answer: "Sur place, lors d’un créneau d’accueil : visite du lieu, fiche d’adhésion et explication de l’autogestion. Pas d’inscription en ligne — on fait ça ensemble au lieu pour que chacun·e parte avec les mêmes repères."
},
{
question: "Paiement adhésion ou cotisation",
answer: "Carte bancaire ou espèces à l’accueil, avec les bénévoles."
},
{
question: "Je débute : les entraînements libres me concernent ?",
answer_html: helpers.safe_join([
"Les créneaux libres cirque sont pour des pratiquant·es autonomes en sécurité. Pour apprendre les bases, une école partenaire ; pour une orientation, ",
helpers.link_to("écris-nous", cf, class: lc),
" en Question générale."
])
}
]
end

def general_faq_entries
cf = page_path("contact_us", anchor: "contact-form")
bm = page_path("become_member", anchor: "tarifs")
lc = "text-[#5836A5] underline hover:text-[#412886]"
[
{ question: "Où se situe le Circographe ?", answer: "Au 27 bis allée Maurice Sarraut, Toulouse — dans le quartier de la Cartoucherie. Consulte la page Contact pour la carte et l'accès." },
{ question: "Quels sont les horaires d'ouverture ?", answer: "Les créneaux publics évoluent chaque saison ; on les met à jour sur les pages Accueil, Adhérer et Contact. Pense à vérifier avant de te déplacer." },
{ question: "Comment soutenir financièrement le projet ?", answer: "En adhérant, en souscrivant à l'adhésion soutien ou en faisant un don ponctuel. Écris-nous si tu souhaites devenir partenaire." },
{ question: "J'ai une question administrative, qui contacter ?", answer: "Utilise le formulaire de contact (catégorie 'Question générale') ou écris à [email protected] ; l'équipe bénévole te répondra rapidement." }
{
question: "Adresse et accès",
answer_html: helpers.safe_join([
"97 bis boulevard de Suisse, 31200 Toulouse. ",
helpers.link_to("Plan et bus (ligne 15)", page_path("contact_us", anchor: "map"), class: lc),
"."
])
},
{
question: "Horaires",
answer: "Les créneaux publics bougent selon la saison et les bénévoles. À jour sur l’accueil, la page Adhérer et la page Contact — jette un œil avant de venir."
},
{
question: "Soutenir le lieu ou une question administrative",
answer_html: helpers.safe_join([
"Adhérer, cotisation, don : ",
helpers.link_to("page Adhérer", bm, class: lc),
". Pour un partenariat, un don hors cadre ou une demande administrative : ",
helpers.link_to("formulaire Contact", cf, class: lc),
" (Question générale ou Partenariat)."
])
}
]
end

Expand Down
7 changes: 7 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ def available_hero_images(except: [])
fallback && exclusions.exclude?(fallback.to_s) ? [ fallback ] : []
end

# Filenames under app/assets/images/ (same pool as hero_image). Sorted for stable order.
# Swiper receives several slides but only the first image uses eager loading.
def news_carousel_image_sources(limit: 12)
max_slides = limit.to_i.clamp(1, 24)
hero_image_pool.uniq.sort.take(max_slides)
end

def asset_available?(logical_path)
return false if logical_path.blank?

Expand Down
103 changes: 103 additions & 0 deletions app/javascript/controllers/map_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Controller } from "@hotwired/stimulus"
import * as L from "leaflet"
Comment thread
AkaKwak marked this conversation as resolved.
Outdated

export default class extends Controller {
static values = {
lat: Number,
lng: Number,
zoom: { type: Number, default: 17 }
}

connect () {
this._disconnected = false
this._lastSize = { w: 0, h: 0 }
this._resizeFrame = null

// Attendre 2 frames : la grille / le turbo-frame ont souvent une hauteur encore à 0 au premier paint.
requestAnimationFrame(() => {
requestAnimationFrame(() => {
if (this._disconnected || !this.element.isConnected) return
this._initMap()
})
})
}

_initMap () {
if (this._disconnected || !this.element.isConnected) return

this._resizeTimeouts = []

const scheduleInvalidate = (force = false) => {
if (!this.map) return
if (this._resizeFrame != null) cancelAnimationFrame(this._resizeFrame)
this._resizeFrame = requestAnimationFrame(() => {
this._resizeFrame = null
const el = this.element
const w = el.clientWidth
const h = el.clientHeight
if (w <= 0 || h <= 0) return
if (!force && w === this._lastSize.w && h === this._lastSize.h) return
this._lastSize = { w, h }
this.map.invalidateSize({ animate: false })
})
}

this.boundTurboFrameLoad = (e) => {
if (e.target.contains(this.element)) scheduleInvalidate(true)
}
document.addEventListener("turbo:frame-load", this.boundTurboFrameLoad)

this.boundWindowResize = () => scheduleInvalidate(true)
window.addEventListener("resize", this.boundWindowResize)

this.map = L.map(this.element).setView([this.latValue, this.lngValue], this.zoomValue)

// Tuiles raster via CARTO (cartocdn.com) ; rendu 100 % Leaflet côté navigateur (pas d’iframe ni SDK tiers).
L.tileLayer("https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png", {
attribution:
'&copy; <a href="https://wiki.osmfoundation.org/wiki/Licence" rel="nofollow noopener">Sources des données</a> · <a href="https://carto.com/attributions" rel="nofollow noopener">CARTO</a>',
subdomains: "abcd",
maxZoom: 19
}).addTo(this.map)

// Pas d’images CDN (évite icône cassée si cdnjs / tracking bloqués) — cercle aux couleurs du site.
L.circleMarker([this.latValue, this.lngValue], {
radius: 10,
color: "#1F5C55",
fillColor: "#5836A5",
fillOpacity: 0.9,
weight: 3
}).addTo(this.map).bindPopup("<strong>Le Circographe</strong><br>97 bis bd de Suisse, Toulouse")

this.map.whenReady(() => {
scheduleInvalidate(true)
;[120, 350, 700].forEach(ms => {
const id = setTimeout(() => scheduleInvalidate(true), ms)
this._resizeTimeouts.push(id)
})
})

this.resizeObserver = new ResizeObserver(() => scheduleInvalidate(false))
this.resizeObserver.observe(this.element)
}

disconnect () {
this._disconnected = true
this._resizeTimeouts?.forEach(id => clearTimeout(id))
this._resizeTimeouts = null
if (this.boundTurboFrameLoad) {
document.removeEventListener("turbo:frame-load", this.boundTurboFrameLoad)
this.boundTurboFrameLoad = null
}
if (this.boundWindowResize) {
window.removeEventListener("resize", this.boundWindowResize)
this.boundWindowResize = null
}
if (this._resizeFrame != null) cancelAnimationFrame(this._resizeFrame)
this._resizeFrame = null
this.resizeObserver?.disconnect()
this.resizeObserver = null
this.map?.remove()
this.map = null
}
}
8 changes: 8 additions & 0 deletions app/javascript/controllers/slider_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ export default class extends Controller {
}

const options = Object.assign({}, defaultOptions, this.optionsValue || {})

if (options.pagination?.el && typeof options.pagination.el === "string") {
const paginationEl = this.element.querySelector(options.pagination.el)
if (paginationEl) {
options.pagination = { ...options.pagination, el: paginationEl }
}
}

const slideCount = this.element.querySelectorAll(".swiper-slide").length
const breakpointValues = Object.values(options.breakpoints || {}).map(cfg => cfg.slidesPerView || options.slidesPerView)
const maxSlidesPerView = Math.max(options.slidesPerView || 1, ...breakpointValues, 1)
Expand Down
Loading